I'm trying to translate this code into python from c,
} else if(remaining == 3) {
firstB = (BYTE*)&buf[0];
*firstB ^= 0x12;
firstW = (WORD*)&buf[1];
*firstW ^= 0x1234;
i = 3;
}
for(; i<len;)
{
then = (DWORD*)&buf[i];
*then ^= 0x12345678;
i += 4;
}
What I got:
elif remaining == 3:
new_packet.append(struct.unpack('<B', packet_data[0:1])[0] ^ 0x12)
new_packet.append(struct.unpack('<H', packet_data[1:3])[0] ^ 0x1234)
i = 3
while i < packet_len:
new_packet.append(struct.unpack('<L', packet_data[i:i+4])[0] ^ 0x12345678)
i += 4
return new_packet
problem is I always get ValueError: byte must be in range(0, 256).
So I must be translating this wrong. So what am I missing or is there any way I can make this more efficient? Why is the python code wrong?
update
new_bytes = struct.unpack('<H', packet_data[1:3])
new_packet.append(new_bytes[0] ^ 0x1234)
I'm getting the first few bytes right with above, but nothing ever right with code below:
new_bytes = struct.unpack('<BB', packet_data[1:3])
new_packet.append(new_bytes[0] ^ 0x12)
new_packet.append(new_bytes[1] ^ 0x34)
So my problem still remains inside the while loop, and the question remains how to do this right:
new_bytes = struct.unpack('<L', packet_data[i:i+4])
new_packet.append(new_bytes[0] ^ 0x12345678)
This line
new_packet.append(struct.unpack('<H', packet_data[1:3])[0] ^ 0x1234)
tries to append a two-byte value to the byte array. One fix is to append the two bytes of the word separately:
# Little-endian, so the first byte is low byte of the word.
new_bytes = struct.unpack('BB', packet_data[1:3])
new_packet.append(new_bytes[0] ^ 0x34)
new_packet.append(new_bytes[1] ^ 0x12)
# Similarly for the 4-byte value
new_bytes = struct.unpack('BBBB', packet_data[i:i+4])
new_packet.append(new_bytes[0] ^ 0x78)
new_packet.append(new_bytes[1] ^ 0x56)
new_packet.append(new_bytes[2] ^ 0x34)
new_packet.append(new_bytes[3] ^ 0x12)
Related
So I am lost on how to make a hexadecimal to ascii code. I am doing this for educational purposes. I am still learning about cryptography and python in general. I do not know the code for decrypting Hex to ASCII. My converting to hex string will have an error and it will not get an input from the user.
def crib_drag_attack(guess, cp1, cp2):
xor_ciphers = ""
for idx in range(len(cp1)):
ic1 = ord(cp1[idx])
ic2 = ord(cp2[idx])
ic_xor = ic1 ^ ic2
xor_ciphers += chr(ic_xor)
for idx in range(len(xor_ciphers) - len(guess)+1):
slide = xor_ciphers[idx: idx + len(guess)]
results = ""
for i in range(len(guess)):
ig = ord(guess[i])
id = ord(slide[i])
ir = ig ^ id
results += chr(ir)
print(results)
def encrypt(key, plaintext):
idx = 0 # Declare index (idx) variable
ciphertext = "" # Declare ciphertext variable
for p in plaintext: # Take one character at a time in message
ip = ord(p) # Convert to Decimal value code
k = key[idx] # Take byte value of the key at idx
ik = ord(k) # Convert to Decimal value code
inew = ip ^ ik # XOR bit-by-bit
ciphertext += chr(inew) # Convert to character code and Update ciphertext
print(p, hex(ip), k, hex(ik), hex(inew)) # print every result
idx += 1 # Increment idx by 1
hexstring = ciphertext.encode("ascii").hex()
print("\n{} --> {}\n".format(ciphertext, hexstring))
trial = bytes.fromhex(hexstring).decode("ascii")
print("Trial: {}".format(trial))
return ciphertext
def decrypt(key, ciphertext):
idx = 0 # Declare index (idx) variable
plaintext = "" # Declare plaintext variable
for c in ciphertext: # Take one character at a time in message
ic = ord(c) # Convert to Decimal value code
k = key[idx] # Take byte value of the key at idx
ik = ord(k) # Convert to Decimal value code
inew = ic ^ ik # XOR bit-by-bit
plaintext += chr(inew) # Convert to character code and Update ciphertext
print(c, hex(ic), k, hex(ik), hex(inew)) # print every result
idx += 1 # Increment idx by 1
print("\n{} --> {}\n".format(plaintext, plaintext.encode("ascii").hex()))
return plaintext
if __name__ == '__main__':
# ciphertext1 = encrypt(key, message1)
# plaintext1 = decrypt(key, ciphertext1)
# #
# ciphertext2 = encrypt(key, message2)
# plaintext1 = decrypt(key, ciphertext2)
# place the given ciphertext 1 and 2 below
#
# Insert the hex string below
ciphertextHex1 = ""
ciphertextHex2 = ""
# Convert the hex string to ascii string
quote_h = "300d04014"
quote = binascii.a2b_hex("%s" %
(quote_h.strip())).decode("ASCII").replace(';', '\n- ')
print(quote)
guess = input("Guess a word: ")
crib_drag_attack(guess, ciphertext1, ciphertext2)
Your code is not so "pythonic". Let's try another way...
Firstly how to properly convert formats from Hex to bytes etc...
The most recommended way to convert hex to bytes is this one:
quote_h = "0300d04014" # added a zero at the beginning because you give 9 characters and in python, in this situation we just add prefix `0`.
quote = bytes.fromhex(quote_h)
Next thing you need to keep in mind...
When dealing with cryptography, it's not recommended to .decode() things because str does not support all the byte values as like encoded strings.
Next thing is a much more pythonic way to xor values...
I want to xor 12345 with your quote_h variable:
key = b'12345'.hex() # '3132333435'
quote_h = "0300d04014"
key = int(key, 16) # From hex to integer | 211295614005
quote = int(quote_h, 16) # From hex to integer | 12898549780
key_xor_quote = key ^ quote # 215602132001
key_xor_quote_h = hex(key_xor_quote)[2:] # From integer to hex without the '0x' prefix | '3232e37421'
# ATTENTION: Be careful here because if the first characters
# in hex format where zeros, then hex() would pass
# them and the result would be something
# like this 300d04014 which is invalid because you miss the first zero
# and you will get invalid error in the next command.
# Try to think a way to handle this situation.
key_xor_quote_bytes = bytes.fromhex(key_xor_quote_h) # b'22\xe3t!'
Here is exactly what you need to know, good luck on the implementation ;)
The problem itself is simple. I have to count the number of occurence of s2 in s1.
And length of s2 is always 2. I tried to implement it with C, but it did not work even though i know the logic is correct. So i tried the same logic in pyhton and it works perfectly. Can someone explain why? Or did i do anything wrong in C. I given both codes below.
C
#include<stdio.h>
#include<string.h>
int main()
{
char s1[100],s2[2];
int count = 0;
gets(s1);
gets(s2);
for(int i=0;i<strlen(s1);i++)
{
if(s1[i] == s2[0] && s1[i+1] == s2[1])
{
count++;
}
}
printf("%d",count);
return 0;
}
Python
s1 = input()
s2 = input()
count = 0
for i in range(0,len(s1)):
if(s1[i] == s2[0] and s1[i+1] == s2[1]):
count = count+1
print(count)
Your python code is actually incorrect, it would raise an IndexError if the last character of s1 matches the first of s2.
You have to stop iterating on the second to last character of s1.
Here is a generic solution working for any length of s2:
s1 = 'abaccabaabaccca'
s2 = 'aba'
count = 0
for i in range(len(s1)-len(s2)+1):
if s2 == s1[i:i+len(s2)]:
count += 1
print(count)
output: 3
First, as others have pointed out, you do not want to use gets(), try using fgets(). Otherwise, your logic is correct but when you read in the input, the new line character will be included in the string.
If you were to input test and es, your strings will contain test\n and es\n (with both respectively containing the null terminating byte \0). Then leads to you searching the string test\n for the substring es\n which it will not find. So you must first remove the new line character from, at least, the substring you want to search for which you can do with strcspn() to give you es.
Once the trailing newline (\n) has been replaced with a null terminating byte. You can search the string for occurances.
#include<stdio.h>
#include<string.h>
int main() {
char s1[100], s2[4];
int count = 0;
fgets(s1, 99, stdin);
fgets(s2, 3, stdin);
s1[strcspn(s1, "\n")] = '\0';
s2[strcspn(s2, "\n")] = '\0';
for(int i=0;i < strlen(s1) - 1;i++) {
if(s1[i] == s2[0] && s1[i+1] == s2[1]) {
count++;
}
}
printf("%d\n",count);
return 0;
}
In Java, it's necessary to strip with \r\n, e.g. split( "\r\n") is not splitting my string in java
But is \r\n necessary in Python? Is the following true?
str.strip() == str.strip('\r\n ')
From the docs:
Return a copy of the string with the leading and trailing characters
removed. The chars argument is a string specifying the set of
characters to be removed. If omitted or None, the chars argument
defaults to removing whitespace. The chars argument is not a prefix or
suffix; rather, all combinations of its values are stripped
From this CPython test, str.strip() seems to be stripping:
\t\n\r\f\v
Anyone can point me to the code in CPython that does the string stripping?
Are you looking for these lines?
https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Objects/unicodeobject.c#L12222-L12247
#define LEFTSTRIP 0
#define RIGHTSTRIP 1
#define BOTHSTRIP 2
/* Arrays indexed by above */
static const char *stripfuncnames[] = {"lstrip", "rstrip", "strip"};
#define STRIPNAME(i) (stripfuncnames[i])
/* externally visible for str.strip(unicode) */
PyObject *
_PyUnicode_XStrip(PyObject *self, int striptype, PyObject *sepobj)
{
void *data;
int kind;
Py_ssize_t i, j, len;
BLOOM_MASK sepmask;
Py_ssize_t seplen;
if (PyUnicode_READY(self) == -1 || PyUnicode_READY(sepobj) == -1)
return NULL;
kind = PyUnicode_KIND(self);
data = PyUnicode_DATA(self);
len = PyUnicode_GET_LENGTH(self);
seplen = PyUnicode_GET_LENGTH(sepobj);
sepmask = make_bloom_mask(PyUnicode_KIND(sepobj),
PyUnicode_DATA(sepobj),
seplen);
i = 0;
if (striptype != RIGHTSTRIP) {
while (i < len) {
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
if (!BLOOM(sepmask, ch))
break;
if (PyUnicode_FindChar(sepobj, ch, 0, seplen, 1) < 0)
break;
i++;
}
}
j = len;
if (striptype != LEFTSTRIP) {
j--;
while (j >= i) {
Py_UCS4 ch = PyUnicode_READ(kind, data, j);
if (!BLOOM(sepmask, ch))
break;
if (PyUnicode_FindChar(sepobj, ch, 0, seplen, 1) < 0)
break;
j--;
}
j++;
}
return PyUnicode_Substring(self, i, j);
}
Essentially:
str.strip() == str.strip(string.whitespace) == str.strip(' \t\n\r\f\v') != str.strip('\r\n')
Unless you are explicitly trying to remove ONLY newline characters, str.strip() and str.strip('\r\n') are different.
>>> '\nfoo\n'.strip()
'foo'
>>> '\nfoo\n'.strip('\r\n')
'foo'
>>> '\r\n\r\n\r\nfoo\r\n\r\n\r\n'.strip()
'foo'
>>> '\r\n\r\n\r\nfoo\r\n\r\n\r\n'.strip('\r\n')
'foo'
>>> '\n\tfoo\t\n'.strip()
'foo'
>>> '\n\tfoo\t\n'.strip('\r\n')
'\tfoo\t'
This all seems fine, but note that if there is whitespace (or any other character) between a newline and the start or end of a string, .strip('\r\n') won't remove the newline.
>>> '\t\nfoo\n\t'.strip()
'foo'
>>> '\t\nfoo\n\t'.strip('\r\n')
'\t\nfoo\n\t'
I am not really familiar with Python yet.
I have a string like "11223300". Now I want to increase the last byte of that string ( from "00" to "FF"). I tried to convert the string into an integer ( integer=int(string,16)) and increase it, and convert it back later, but that does not work for me. Maybe one of you guys has a better idea.
string = "11223300"
counter = int(string, 16)
for i in range(255):
counter = counter + 1
IV = hex(counter)
Now I want to convert the IV from hex into a string
Thanks!
You can use format to convert int to your hex string, which will not keep the 0x prefix:
string = "11223300"
counter = int(string, 16)
for i in range(255):
counter = counter + 1
IV = format(counter, 'X')
print(IV)
Output:
112233FF
The function below takes a string and increases it by n from a given charset
For example, in the charset ['a','b','c'] :
"aaa" + 1 = "aab"
"aac" + 1 = "aba"
"acc" + 2 = "bab"
def str_increaser(mystr, charset, n_increase):
# Replaces a char in given string & index
def replace_chr_in_str(mystr, index, char):
mystr = list(mystr)
mystr[index] = char
return ''.join(mystr)
# Increases the char last (n) and possibly its left neighboor (n-1).
def local_increase(mystr, charset):
l_cs = len(charset)
# increasing 1 to last char if it's not the last char in charset (e.g. 'z' in lowercase ascii).
if (charset.index(mystr[-1]) < l_cs - 1):
mystr = replace_chr_in_str(mystr, -1, charset[charset.index(mystr[-1]) + 1])
# else, reset last char to the first one in charset and increase the its left char, using a reducted string for recursion
else:
mystr = replace_chr_in_str(mystr, -1, charset[0])
mystr = local_increase(mystr[:-1], charset) + mystr[-1]
return mystr
# Case if input = "zz...zz" in an ascii lowercase charset for instance
if (mystr == charset[-1] * len(mystr)):
print("str_increaser(): Input already max in charset")
else:
for i in range(n_increase):
mystr = local_increase(mystr, charset)
return mystr
Here's an exemple :
# In bash : $ man ascii
# charset = map(chr, range(97, 123)) + map(chr, range(65, 91))
import string
charset = string.lowercase + string.uppercase
print(str_increaser("RfZ", charset, 2)) # outputs "Rgb"
This function might be used to get all permutations in some charsets.
So are you literally wanting to change the last two bits of the string to "FF"? If so, easy
string = "11223300"
modified_string = string[:-2] + "FF"
Edit from comments
hex_str = "0x11223300"
for i in range(256):
hex_int = int(hex_str, 16)
new_int = hex_int + 0x01
print(hex(hex_int))
hex_str = str(hex(new_int))
For the fun of it, I am trying to bitwise rotate a whole text to right. Meaning, I want every character's last bit (lsb) end up being next character's first bit (msb) and last character's last bit to be first character's first bit. Here is what I have tried;
def bitwise_text_rotate(text):
# make a list of ascii codes
characters = [ord(a) for a in text]
# save last character's right-most bit
carry_bit = characters[-1] & 1
# list of processed characters
output = []
for char in characters:
print "processing", char
last_bit = char & 1
char = char >> 1
mask = (carry_bit << 8) & 1
char = char & mask
print "appending", char
output.append(char)
carry_bit = last_bit
return "".join([chr(a) for a in output])
But it doesn't work. I am getting all zeros. Any ideas how I could do this better, or what am I doing wrong here?
Try this:
s = map(ord, text)
return ''.join(chr(((a&1)<<7) + (b>>1)) for a,b in zip(s[-1:] + s, s))
These lines are incorrect:
mask = (carry_bit << 8) & 1
char = char & mask
Use:
mask = carry_bit << 7
char = char | mask