I have a number like 0x5423 where I want to extract 4 values:
a = 0x5 # 15 downto 12
b = 0x42 # 11 downto 3
c = 0x3 # 3 downto 2
d = 0x00 # 1 downto 0
I discovered the module bitstrings that looks great. Unfortunately, for an unknown reason, the bits are numbered from the right.
This is bad because if a add some upper bits like 0xA5423 my extraction won't work anymore:
field = bitstrings.BitArray('0x5423')
a = field[0:4].uint
b = field[4:12].uint
c = field[12:14].uint
d = field[14:16].uint
How can I properly extract my bitfields without complex arithmetic manipulations such as:
b = (a >> 4) & 0xFF
Ideally I would have:
b = field.range(11, 4)
Convert the string to 0x#### format before pass to bitstring.BitArray:
>>> n = '0xA5423'
>>> n = '0x{:04x}'.format(int(n, 16) & 0xffff) # => '0x5423'
>>> field = bitstring.BitArray(n)
>>> field[0:4].uint
5
>>> field[4:12].uint # 0x42 == 66
66
>>> field[12:14].uint
0
>>> field[14:16].uint
3
UPDATE another solution that does not depend on bitstring, and count from left(according to OP):
Convert the number into binary format:
>>> n = '0xA5423'
>>> n = format(int(n, 16), '016b')[::-1] # reversed
>>> n
'11000100001010100101'
>>> int(n[0:2][::-1], 2) # need to reverse again to get proper value
3
>>> int(n[2:4][::-1], 2)
0
>>> int(n[4:12][::-1], 2)
66
>>> int(n[12:16][::-1], 2)
5
Related
is there any way to output the difference between two float numbers as an integer
below is three examples of the float values provided for script, my goal is to output the difference between these values as an integer , in the first example i should get 2 where num_two - num_one equals 0.000002 but i don't want the zeros as they don't matter i can do it with string format but i have no way of telling how big the number is or how many zeros it has
## example 1
num_one = 0.000012
num_two = 0.000014
## example 2
num_0ne = 0.0123
num_tw0 = 0.013
## example 3
num_1 = 23.32
num_2 = 23.234
print (float(num_2) - float(num_1))
## this should output 86 as an integer
Beware of floats (see https://en.wikipedia.org/wiki/IEEE_754):
>>> 23.32 - 23.234
0.08599999999999852
You need exact precision. Use the decimal module:
>>> from decimal import Decimal
>>> n1 = Decimal("23.32")
>>> n2 = Decimal("23.234")
>>> n1, n2
(Decimal('23.32'), Decimal('23.234'))
>>> d = abs(n1-n2)
>>> d
Decimal('0.086')
Now, just shift the decimal point right (that is * 10) until there is no fractional part left (d % 1 == 0):
>>> while d % 1:
... d *= 10
(Don't be afraid, the loop will stop because you can't have more decimal levels than decimal.getcontext().prec at the beginning and the decimal level decrease on each iteration).
You get the expected result:
>>> d
Decimal('86.000')
>>> int(d)
86
In Java right rotation is done using:
(bits >>> k) | (bits << (Integer.SIZE - k))
But how to do similar thing in Python?
I tried to do (as described here):
n = 13
d = 2
INT_BITS = 4
print(bin(n))
print(bin((n >> d)|(n << (INT_BITS - d)) & 0xFFFFFFFF))
Output:
0b1101
0b110111
But I could not interpret this as a right rotation.
Also is it possible to perform the rotation by excluding leading zeroes, for example:
rightRotation of (...0001101) = 1110 not 1000...110
It is my mistake, if you want to change INT_BITS to 4 you also need to change 0xFFFFFFFF to 0xF (one hex equals 4-bits):
n = 13
d = 2
INT_BITS = 4
print(bin(n))
print(bin((n >> d)|(n << (INT_BITS - d)) & 0xF))
will output:
0b1101
0b111
How we could code the reverse complete of a DNA sequence from its code?
A DNA sequence can contain 4 different characters A, C, G, T; where A is the complement of T and C is the complement of G.
A reverse complement of A DNA sequence is the complement of a sequence but in an inverse way (we compute the complement of each character from right to left).
Example: the complement of (AA) is: TT, the complement of (AC) is GT and so on...
In general, using python we code a sequence by mapping each character to a number going from 0 to 3,
{A:0, C:1, G:2, T:3}
then the coding of AA is: 0, the coding of AC is:
AC = 0*4^0+1*4^1 = 4
the coding of GT is:
GT = 2*4^0+3*4^1 = 14
How could I transform the code of each sequence to its reverse complement in python without creating a dictionary? For the above example: convert 4 to 14? and 0 to 15 ...
Your symbol set is too small for a hash map to actually be efficient. And mixing two's complement into your problem has just caused confusion.
symbols = 'ACGT'
complements = symbols[::-1] # reverse order
import string
table = string.maketrans(symbols, complements)
sample = 'ACCGTT'
print(sample[::-1].translate(table))
# output: AACGGT
Converting to some bitpacked format would take less space but require a lot more special handling, as you'd need to track sizes separately, perform arbitrarily wide shifts and so on. Python can certainly do it, in particular with int() accepting many bases and creating arbitrary width results, but it's likely a counterproductive detour.
digits = string.digits[:len(symbols)]
length = len(sample)
digitmap = string.maketrans(symbols, digits)
number = int(sample.translate(digitmap), len(digits))
def reversemapnumber(function=id, number=0, radix=0b100, length=0):
result = 0
for i in range(length):
number,digit = divmod(number, radix)
result = result*radix + function(digit)
return result
revcomplemented = reversemapnumber(function=lambda x: 3-x,
number=number, length=length)
# binary form
print('{:0{}b}'.format(revcomplemented, length*2))
# back to text form
print(''.join(symbols[(revcomplemented>>i)&0b11]
for i in range(2*length-2, -2, -2)))
In that jumble of code I've used division rather than shifts to be somewhat more generic (supporting radix not a power of two), but the printing examples rely on the width exactly. In the end it's just tricky and unclear.
the reverse of a list in python
>>> xs = [1,2,3]
>>> reversed(xs)
<listreverseiterator object at 0x10089c9d0>
>>> list(reversed(xs))
[3, 2, 1]
>>>
def complement(x):
return ~x & 15 # as 15 == int('1111', 2)
the 15 is a bitmask. It represents the binary 1111. We then use the binary and operator.
>>> "{0:b}".format(complement(int('1111',2)))
'0'
>>> "{0:b}".format(complement(int('0001',2)))
'1110'
>>> "{0:b}".format(complement(int('1001',2)))
'110'
>>> xs = [int('1111',2), int('1001',2), int('0110',2), int('1011',2)]
>>> map(complement, xs)
[0, 6, 9, 4]
>>> list(reversed(map(complement, xs)))
[4, 9, 6, 0]
Basing your example where
given a sequence of 6 characters: ACCGTT, the complement of A is: T,
and the complement of C is G; so the reverse complement of ACCGTT is: AACGGT.
assume that you have c complemnt function complement and a reverse function reverse.
we have reverse(ACCGTT) = TTGCCA and complement(ACCGTT) = TGGCAA
. Reversing a list after calling a function on each element is the same as calling a function on each element on a list.
complement(reverse(ACCGTT)) = reverse(complement(ACCGTT))
So the other part of the question is that you want to map
{A:0, C:1, G:2, T:3}
A -> T | 0 -> 3
T -> A | 3 -> 0
C -> G | 1 -> 2
G -> C | 2 -> 1
which in binary would be
a = int('00', 2) # 0
c = int('01', 2) # 1
g = int('10', 2) # 2
t = int('11', 2) # 3
def complement(x):
return ~x & 3 # this 3 is the same as int('11', 2)
def reverse_complement(list_of_ints):
return list(reversed(map(complement, list_of_ints)))
How i can create a frame icmp
I mark malformet packet on python
import socket, struct, uuid, subprocess, fcntl, time,random
List item
from binascii import hexlify, unhexlify from datetime import datetime
tarRed = raw_input('Ingrese nombre de Tarjeta de Red Utilizada: ')
subprocess.call(['ifconfig', tarRed, 'promisc']) pt = 0x0800 s =
socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(pt))
s.bind((tarRed, pt))
#GETCheck def getchecksum(ip_header,size): cksum = 0 pointer = 0 while size > 1: cksum += int((str("%02x" % (ip_header[pointer],))
+ str("%02x" % (ip_header[pointer+1],))), 16) size -= 2 pointer += 2 #if size: #This accounts for a situation where the header is odd
#cksum += int(ip_header[pointer]) cksum = (cksum >> 16) +
(cksum & 0xffff) cksum += (cksum >>16) return (~cksum) &
0xFFFF def _checksum(data): #calculate the header sum
ip_header_sum = sum(struct.unpack_from("6H", data)) #add the carry
ip_header_sum = (ip_header_sum & 0xFFFF) + (ip_header_sum >> 8 &
0xFFFF) ip_header_sum = ~ip_header_sum & 0xFFFF return
ip_header_sum def i_checksum(checksum_packet): total = 0 num_words
= len(checksum_packet) / 2 for chunk in struct.unpack("!%sH" % num_words, checksum_packet[0:num_words*2]): total += chunk if
len(checksum_packet) % 2: total += ord(checksum_packet[-1]) << 8
total += total >> 16 return (~total + 0xffff & 0xffff)
def checksum(source_string): sum = 0 countTo =
(len(source_string)/2)*2 count = 0 while count<countTo:
thisVal = ord(source_string[count + 1])*256 + ord(source_string[count]) sum = sum + thisVal sum = sum &
0xffffffff
count = count + 2 if countTo<len(source_string): sum = sum + ord(source_string[len(source_string) - 1]) sum = sum &
0xffffffff sum = (sum >> 16) + (sum & 0xffff) sum = sum + (sum
>> 16) answer = ~sum answer = answer & 0xffff #answer = answer >> 8 | (answer << 8 & 0xff00) return answer def
checksuma(source_string): sum = 0 countTo =
(len(source_string)/2)*2 count = 0 while count<countTo:
thisVal = ord(source_string[count + 1])*256 + ord(source_string[count]) sum = sum + thisVal sum = sum &
0xffffffff
count = count + 2 if countTo<len(source_string): sum = sum + ord(source_string[len(source_string) - 1]) sum = sum &
0xffffffff sum = (sum >> 16) + (sum & 0xffff) sum = sum + (sum
>> 16) answer = ~sum answer = answer & 0xffff answer = answer >> 8 | (answer << 8 & 0xff00) return answer def ultimo(str):
csum = 0
countTo = (len(str) / 2) * 2
count = 0
while count < countTo:
thisVal = ord(str[count+1]) * 256 + ord(str[count])
csum = csum + thisVal
csum = csum & 0xffffffff
count = count + 2
if countTo < len(str):
csum = csum + ord(str[len(str) - 1])
csum = csum & 0xffffffff
csum = (csum >> 16) + (csum & 0xffff)
csum = csum + (csum >> 16)
answer = ~csum
answer = answer & 0xffff
answer = answer >> 8 | (answer << 8 & 0xff00)
return answer
#GETCheck
#MACs adst='ffffffffffff' mac_destino = unhexlify(adst) ma = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info =
fcntl.ioctl(ma.fileno(), 0x8927, struct.pack('256s', tarRed[:15]))
asrc = ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
sd = asrc.split(':') asrc = sd[0]+sd[1]+sd[2]+sd[3]+sd[4]+sd[5]
mac_origen = unhexlify(asrc)
#MACs cabEther = struct.pack('!6s6sh',mac_destino,mac_origen,pt)
#datosIP
#version = '4'
#IHL = '5' tipoServicio = unhexlify('00') longitudT = struct.pack('!BB',00,24) identificador = struct.pack('!BB',00,01)
flag_Pos = 0x4000 tiempoVida = 05 ptIP = unhexlify('01') SCC = 0
#IPs ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ipO= str( socket.inet_ntoa(fcntl.ioctl(ip.fileno(),0x8915,struct.pack('256s',
tarRed[:15]))[20:24])) ipO1 = ipO.split('.') ipOr =
struct.pack("!BBBB",int(ipO1[0]),int(ipO1[1]),int(ipO1[2]),int(ipO1[3]))
ipD = raw_input('Ingrese la direccion IP destino: ') ipD1 =
ipD.split('.') ipDest =
struct.pack("!BBBB",int(ipD1[0]),int(ipD1[1]),int(ipD1[2]),int(ipD1[3]))
#IPs
#datosIP cabIP = struct.pack('!1s1s2s2shB1sH4s4s',unhexlify('45'),tipoServicio,longitudT,identificador,flag_Pos,tiempoVida,ptIP,SCC,ipOr,ipDest)
SCC = checksum(cabIP) cabIP =
struct.pack('!1s1s2s2shB1sH4s4s',unhexlify('45'),tipoServicio,longitudT,identificador,flag_Pos,tiempoVida,ptIP,socket.htons(SCC),ipOr,ipDest)
#datosIcmp tipo = 8 codigo = 0x00 check = 0x0000 identificador = int((id(1) * random.random()) % 65535) secuencia = 0x0000
#datos = 'qwertyasdfghzxcvbn0102030405060708091011121314151617181920' datos =
1 * 'Q'
#datosIcmp cabIcmp = struct.pack('!bbHHh',tipo,0,0,identificador,1) my_checksum = ultimo(cabIcmp + datos) cabIcmp =
struct.pack('!bbHHh',tipo,0,socket.htons(my_checksum),identificador,1)
cabIcmp = cabIcmp + datos tiempo = datetime.now() print tiempo for i
in range(15): s.send(cabEther + cabIP + cabIcmp,0)
Your question is barely understandable. It appears you're asking how to create an ICMP ECHO packet since the packet you are creating in the listed code is reported as malformed by your system. I'll try to answer why your code won't work.
First, the socket type you're using is incorrect. You need type 1, not 8. This can be done easily enough with the third parameter:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
(Note you'll need root or administrator privileges to make this call.)
Second, after creating the socket, you'll need to create the ICMP header. An ICMP header consists of the following structure:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 | Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 | REST OF HEADER |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Notice the second four bytes "REST OF HEADER". This second set of four bytes depends on the TYPE/CODE in the first two bytes. For example, if TYPE is 0 and CODE is 0, it means you're dealing with an echo reply, and as such, the second four bytes will become 2-byte Identifier and 2-byte Sequence Number fields, starting at offset 4 and ending at offset 7 as the picture shows:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 | Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4 | Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8 | Data ...
+-+-+-+-+-
To create this header, I'm going to use type 8, the echo request structure, as such (note that bytes 4-5 and 6-7 in this creation is just for illustration, typically this would be different values other than zero):
icmp = struct.pack(">BBHHH", 8, 0, 0, 0, 0)
On this initial creation of the header, the checksum is zero. What we now need is to actually calculate the checksum (with this zero value), and THEN recreate the header with this new checksum value:
icmp = struct.pack(">BBHHH", 8, 0, cksum(icmp), 0, 0)
But this is where your code is incorrect again. The implementation of i_checksum() is wrong. To fix, I'll leave it to you to figure it out. The checksum is called 1's complement, and there are numerous online articles about it, as well as C code on Linux systems that implement it.
Once you have the header and its correct checksum (important because your system won't send the packet if incorrect), you simply then send it somewhere:
s.sendto(icmp, (SOME_REMOTE_HOST, 0))
And then receive replies if any:
s.recvfrom(1500)
(Note I chose 1500 bytes as that is the MTU of an IP frame, and it is thus unlikely a reply will be bigger than this, though it is certainly possible.)
AND AT THIS POINT, YOUR CODE TOTALLY FAILS -- simply because you do not have code which does the last two steps, let alone additional code to handle what to do with replies and struct-parsing of the header fields.
As for the other two functions you've defined, they're odd. One of them seems to imply it is dealing with link layer fields -- which is never the case on sockets as sockets only deal in IP layer and above -- while the other seems to be an attempt at calculating a checksum...albeit incorrectly (again).
In short, as abarnert implied, please clarify (and add some more) code AND your question.
I want to realize IDEA algorithm in Python. In Python we have no limits for variable size, but I need limit bit number in the integer number, for example, to do cyclic left shift. What do you advise?
One way is to use the BitVector library.
Example of use:
>>> from BitVector import BitVector
>>> bv = BitVector(intVal = 0x13A5, size = 32)
>>> print bv
00000000000000000001001110100101
>>> bv << 6 #does a cyclic left shift
>>> print bv
00000000000001001110100101000000
>>> bv[0] = 1
>>> print bv
10000000000001001110100101000000
>>> bv << 3 #cyclic shift again, should be more apparent
>>> print bv
00000000001001110100101000000100
An 8-bit mask with a cyclic left shift:
shifted = number << 1
overflowed = (number & 0x100) >> 8
shifted &= 0xFF
result = overflowed | shifted
You should be able to make a class that does this for you. With a bit more of the same, it can shift an arbitrary amount out of an arbitrary sized value.
The bitstring module might be of help (documentation here). This example creates a 22 bit bitstring and rotates the bits 3 to the right:
>>> from bitstring import BitArray
>>> a = BitArray(22) # creates 22-bit zeroed bitstring
>>> a.uint = 12345 # set the bits with an unsigned integer
>>> a.bin # view the binary representation
'0b0000000011000000111001'
>>> a.ror(3) # rotate to the right
>>> a.bin
'0b0010000000011000000111'
>>> a.uint # and back to the integer representation
525831
If you want a the low 32 bits of a number, you can use binary-and like so:
>>> low32 = (1 << 32) - 1
>>> n = 0x12345678
>>> m = ((n << 20) | (n >> 12)) & low32
>>> "0x%x" % m
'0x67812345'