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))
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 ;)
I want to convert a string (composed of alphanumeric characters) into an integer and then convert this integer back into a string:
string --> int --> string
In other words, I want to represent an alphanumeric string by an integer.
I found a working solution, which I included in the answer, but I do not think it is the best solution, and I am interested in other ideas/methods.
Please don't tag this as duplicate just because a lot of similar questions already exist, I specifically want an easy way of transforming a string into an integer and vice versa.
This should work for strings that contain alphanumeric characters, i.e. strings containing numbers and letters.
Here's what I have so far:
First define an string
m = "test123"
string -> bytes
mBytes = m.encode("utf-8")
bytes -> int
mInt = int.from_bytes(mBytes, byteorder="big")
int -> bytes
mBytes = mInt.to_bytes(((mInt.bit_length() + 7) // 8), byteorder="big")
bytes -> string
m = mBytes.decode("utf-8")
All together
m = "test123"
mBytes = m.encode("utf-8")
mInt = int.from_bytes(mBytes, byteorder="big")
mBytes2 = mInt.to_bytes(((mInt.bit_length() + 7) // 8), byteorder="big")
m2 = mBytes2.decode("utf-8")
print(m == m2)
Here is an identical reusable version of the above:
class BytesIntEncoder:
#staticmethod
def encode(b: bytes) -> int:
return int.from_bytes(b, byteorder='big')
#staticmethod
def decode(i: int) -> bytes:
return i.to_bytes(((i.bit_length() + 7) // 8), byteorder='big')
If you're using Python <3.6, remove the optional type annotations.
Test:
>>> s = 'Test123'
>>> b = s.encode()
>>> b
b'Test123'
>>> BytesIntEncoder.encode(b)
23755444588720691
>>> BytesIntEncoder.decode(_)
b'Test123'
>>> _.decode()
'Test123'
Recall that a string can be encoded to bytes, which can then be encoded to an integer. The encodings can then be reversed to get the bytes followed by the original string.
This encoder uses binascii to produce an identical integer encoding to the one in the answer by charel-f. I believe it to be identical because I extensively tested it.
Credit: this answer.
from binascii import hexlify, unhexlify
class BytesIntEncoder:
#staticmethod
def encode(b: bytes) -> int:
return int(hexlify(b), 16) if b != b'' else 0
#staticmethod
def decode(i: int) -> int:
return unhexlify('%x' % i) if i != 0 else b''
If you're using Python <3.6, remove the optional type annotations.
Quick test:
>>> s = 'Test123'
>>> b = s.encode()
>>> b
b'Test123'
>>> BytesIntEncoder.encode(b)
23755444588720691
>>> BytesIntEncoder.decode(_)
b'Test123'
>>> _.decode()
'Test123'
Assuming the character set is merely alphanumeric, i.e. a-z A-Z 0-9, this requires 6 bits per character. As such, using an 8-bit byte-encoding is theoretically an inefficient use of memory.
This answer converts the input bytes into a sequence of 6-bit integers. It encodes these small integers into one large integer using bitwise operations. Whether this actually translates into real-world storage efficiency is measured by sys.getsizeof, and is more likely for larger strings.
This implementation customizes the encoding for the choice of character set. If for example you were working with just string.ascii_lowercase (5 bits) rather than string.ascii_uppercase + string.digits (6 bits), the encoding would be correspondingly efficient.
Unit tests are also included.
import string
class BytesIntEncoder:
def __init__(self, chars: bytes = (string.ascii_letters + string.digits).encode()):
num_chars = len(chars)
translation = ''.join(chr(i) for i in range(1, num_chars + 1)).encode()
self._translation_table = bytes.maketrans(chars, translation)
self._reverse_translation_table = bytes.maketrans(translation, chars)
self._num_bits_per_char = (num_chars + 1).bit_length()
def encode(self, chars: bytes) -> int:
num_bits_per_char = self._num_bits_per_char
output, bit_idx = 0, 0
for chr_idx in chars.translate(self._translation_table):
output |= (chr_idx << bit_idx)
bit_idx += num_bits_per_char
return output
def decode(self, i: int) -> bytes:
maxint = (2 ** self._num_bits_per_char) - 1
output = bytes(((i >> offset) & maxint) for offset in range(0, i.bit_length(), self._num_bits_per_char))
return output.translate(self._reverse_translation_table)
# Test
import itertools
import random
import unittest
class TestBytesIntEncoder(unittest.TestCase):
chars = string.ascii_letters + string.digits
encoder = BytesIntEncoder(chars.encode())
def _test_encoding(self, b_in: bytes):
i = self.encoder.encode(b_in)
self.assertIsInstance(i, int)
b_out = self.encoder.decode(i)
self.assertIsInstance(b_out, bytes)
self.assertEqual(b_in, b_out)
# print(b_in, i)
def test_thoroughly_with_small_str(self):
for s_len in range(4):
for s in itertools.combinations_with_replacement(self.chars, s_len):
s = ''.join(s)
b_in = s.encode()
self._test_encoding(b_in)
def test_randomly_with_large_str(self):
for s_len in range(256):
num_samples = {s_len <= 16: 2 ** s_len,
16 < s_len <= 32: s_len ** 2,
s_len > 32: s_len * 2,
s_len > 64: s_len,
s_len > 128: 2}[True]
# print(s_len, num_samples)
for _ in range(num_samples):
b_in = ''.join(random.choices(self.chars, k=s_len)).encode()
self._test_encoding(b_in)
if __name__ == '__main__':
unittest.main()
Usage example:
>>> encoder = BytesIntEncoder()
>>> s = 'Test123'
>>> b = s.encode()
>>> b
b'Test123'
>>> encoder.encode(b)
3908257788270
>>> encoder.decode(_)
b'Test123'
so I needed transfer a dictionary in terms of numbers,
it may look kinda ugly but it's efficient in the way that every char (english letters) is exactly 2 numbers but it's capable of transfering any kind of unicode char
import json
myDict = {
"le key": "le Valueue",
2 : {
"heya": 1234569,
"3": 4
},
'Α α, Β β, Γ γ' : 'שלום'
}
def convertDictToNum(toBeConverted):
return int(''.join([(lambda c: c if len(c) ==2 else '0'+c )(str(ord(c) - 26)) for c in str(json.dumps(toBeConverted))]))
def loadDictFromNum(toBeDecoded):
toBeDecoded = str(toBeDecoded)
return json.loads(''.join([chr(int(toBeDecoded[cut:cut + 2]) + 26) for cut in range(0, len(toBeDecoded), 2)]))
numbersDict = convertDictToNum(myDict)
print(numbersDict)
# 9708827506817595083206088....
recoveredDict = loadDictFromNum(numbersDict)
print(recoveredDict)
# {'le key': 'le Valueue', '2': {'heya': 1234569, '3': 4}, 'Α α, Β β, Γ γ': 'שלום'}
def main():
cc = (input("Enter Message to Encrypt\n"))#user input
shift = int(2) #shift length
a=["a","b","c","d","e","f","g","h","i","j","k","l",
"m","n","o","p","q","r","s","t","u","v","w","x","y","z"] #reference list
newa={} #new shifted reference list
for i in range (0,len(a)):
newa [a[i]]=a[(i+shift)%len(a)]
#adds shifted 2 alaphabet into newalaphabet
#% moodulus used to wrap
for i in cc: #iterates through cc
if i in a:
a[i]=cc[i]
a[i]=newa[i]
main()
So I need input from the user #cc
the shift needs to be two
I used an alphabet list
then shift the alphabet by two to create newa
but I do not know how to apply the new alphabet to my user's input
Use a dictionary to map inputs to outputs
shifted_a = a[-shift:] + a[:-shift]
cipher = {a[i]: shifted_a[i] for i in range(len(a))}
output = ''.join(cipher[char] for char in cc)
Iterate through the string cc and replace all the alphabets using the get method of newa. Characters that are not in the dictionary are left as is, by passing them as the default to newa.get when the key is missing:
newa = {}
for i, x in enumerate(a):
newa[x] = a[(i+shift) % len(a)]
encrypted_text = ''.join(newa.get(i, i) for i in cc)
Python's builtin enumerate can be used in place of range(len(a)) in this case where you need the items in a and their respective indices.
Use mapping for every char, then join them back to create the encrypted message:
''.join(map(lambda x: chr((ord(x) - 97 + shift) % 26 + 97) if x in alphabet else x, cc.lower()))
Integrate it like that:
import string
alphabet = string.ascii_lowercase
cc = input('Enter string to encode: ')
shift = 2 # could be any number
encrypted = ''.join(map(lambda x: chr((ord(x) - 97 + shift) % 26 + 97) if x in alphabet else x, cc.lower()))
cc.lower() for the letters to be all same case (to map using constant ord)
chr((ord(x) - 97 + shift) % 26 + 97) :
get the value of the number minus 97 (0 for a, 1 for b, etc.).
apply the shift (a turns to c, etc.).
modulate by 26 to prevent letters like z from exceeding (25 + 2 = 27, 27 % 26 = 1 = b).
add 97 to bring the letter back to ascii standard (97 for a, 98 for b, etc.)
if x in alphabet else x cover for signs that are not letter (if you want to ignore spaces and punctuation use if x in alphabet else '' instead).
I would just build transition table and use it to decode string.
import string
shift = 2
letters = string.ascii_lowercase + string.ascii_uppercase
transtable = str.maketrans({letters[i]: letters[(i + shift) % len(letters)]
for i in range(len(letters))})
cc = input('Enter string to encode: ')
print(cc.translate(transtable))
I'll throw my solution in there. It should be pretty clear how it works...
import string
index_lookup = {letter: index for index, letter in enumerate(string.ascii_lowercase)}
def caesar_letter(l, shift=2):
new_index = index_lookup[l] + shift
return string.ascii_lowercase[new_index % len(index_lookup)]
def caesar_word(s):
return ''.join([caesar_letter(letter) for letter in s])
I think the above is better for readability but if you're opposed to imports...
index_lookup = {chr(idx): idx - ord('a') for idx in range(ord('a'), ord('z')+1)}
...
In [5]: caesar_word('abcdefghijklmnopqrstuvwxyz')
Out[5]: 'cdefghijklmnopqrstuvwxyzab'
I'm trying to make an encryption function that encrypts plaintext messages but the problem is that if i input a key too large that goes past 'Z' then it goes onto greater unicode values.
My code:
def encrypt(var1,var2):
var3 = ""
for i in range(0, len(var1)):
if ord(var1[i])>64 and ord(var1[i])<90:
var3=var3+chr((ord(var1[i])+var2))
elif ord(var1[i])+var2>90:
???
else:
continue
return(var3)
How do I get it to loop 'Z' back to 'A'. I think I have to make an if statement like this but I'm not sure what to put into it.
elif ord(var1[i])+var2>90:
???
Here is my one! Im using the modulus operator to wrap around every 26 numbers (the number of letter between a-z). I also handle upper on lowercase separately.
def encrypt(data, shift):
result = ''
for c in data:
c_num = ord(c)
# is the letter lower case a - z?
if (c_num >= ord('a')) and (c_num <= ord('z')):
# get the letter number from 0 - 26
c_num = c_num - ord('a')
# shift the number
c_num += shift
# wrap the number every 26 numbers
c_num = c_num % 26
# now increase a by the new amount
c_num += ord('a')
result += chr(c_num)
# is the letter upper case A - Z?
elif (c_num >= ord('A')) and (c_num <= ord('Z')):
# get the letter number from 0 - 26
c_num = c_num - ord('A')
# shift the number
c_num += shift
# wrap the number every 26 numbers
c_num = c_num % 26
# now increase a by the new amount
c_num += ord('A')
result += chr(c_num)
return result
encrypt('aAbB', 2)
'cCdD'
encrypt('afZz', 2)
'chBb'
Here is the code golf version using list comprehension just for fun!
def encrypt(data, shift):
return ''.join([chr(((ord(c) - ord('a') + shift) % 26) + ord('a')) if ord(c) in range(ord('a'), ord('z')+1) else chr(((ord(c) - ord('A') + shift) % 26) + ord('A')) for c in data])
A straight-forward way would be to check if you have passed beyond Z, and modify the character in that case:
...
if var1[i] >= 'A' and var1[i] <= 'Z':
translated_char = chr(ord(var1[i])+var2)
if translated_char > 'Z':
# If the resulting character is beyond Z,
# we go 26 characters back
translated_char = chr(ord(translated_char)-26)
# Append the translated character to the output string
var3 += translated_char
...
You may want to consider more descriptive variable names -- you'll thank yourself if you revisit your code after two months :-)
I would recommend using the modulus operator to do what you are wanting. In python that is the % character. In modulus math. X % Y tells us what the remainder of X / Y is. For example. 27 % 26 is 1. Using this you can get your wrap around that you want. Here is a sample bit of code to encrypt a single character
def encrypt_character( valToEncrypt, keyVal ):
# Update the character to be our standard Alphabet mapping
# A -> 0; B->1 ... Z -> 25
x = ord(valToEncrypt) - ord('A')
# Perform the Encryption
retVal = ( x + keyVal ) % 26
# Translate back to the standard ASCII mapping of the character
# for display in python and translate it back into a string
retVal = chr(retVal + ord('A'))
return retVal
# end encrypt_character
Now if we feed the character "A" Into our encryption algorithm with a key of 13 we get "N" as shown:
>>> encrypt_character("A", 13)
'N'
The decrypt algorithm is very similar, except you do subtraction instead of addtion
def decrypt_character( valToDecrypt, keyVal ):
# Update the character to be our standard Alphabet mapping
# A -> 0; B->1 ... Z -> 25
x = ord(valToDecrypt) - ord('A')
retVal = ( x - keyVal ) % 26
# Translate back to the standard ASCII mapping of the character
# for display in python and translate it back into a string
retVal = chr(retVal + ord('A'))
return retVal
To encrypt a string you can use the following function:
from re import sub
def encrypt_message( message, key ):
# Convert the message text into a plain text with all spaces and
# punctuation removed.
plainText = sub(r'[^A-Z]', '', message.upper())
cipherText = ""
charIndex = 0
# Encrypt the message 1 character at a time
while charIndex < len(plainText):
cipherText += \
encrypt_character( plainText[charIndex], key)
charIndex += 1
return cipherText
This function can be called:
>>> encrypt_message("HELLO World!", key=23)
'EBIILTLOIA'
The decryption function is very similar to the encryption function, except it calls the decrypt utility instead of the encrypt utility.
I am trying to convert alphanumeric string with maximum length of 40 characters to an integer as small as possible so that we can easily save and retrieve from database. I am not aware if there is any python method existing for it or any simple algorithms we can use. To be specific my string will have only characters 0-9 and a-g. So kindly help with any suggestions on how we can uniquely convert from string to int and vice versa. I am using Python 2.7 on Cent os 6.5
This is not that difficult:
def str2int(s, chars):
i = 0
for c in reversed(s):
i *= len(chars)
i += chars.index(c)
return i
def int2str(i, chars):
s = ""
while i:
s += chars[i % len(chars)]
i //= len(chars)
return s
Example:
>>> chars = "".join(str(n) for n in range(10)) + "abcdefg"
>>> str2int("0235abg02", chars)
14354195089
>>> int2str(_, chars)
'0235abg02'
Basically if you want to encode n characters into an integer you interpret it as base-n.
There are 17 symbols in your input, so you can treat is as a base-17 number:
>>> int('aga0',17)
53924
For the reverse conversion, there are lots of solutions over here.
Improving on the above answers:
# The location of a character in the string matters.
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
charsLen = len(chars)
def numberToStr(num):
s = ""
while num:
s = self.chars[num % charsLen] + s
num //= charsLen
return s # Or e.g. "s.zfill(10)"
Can handle strings with leading 0s:
def strToNumber(numStr):
num = 0
for i, c in enumerate(reversed(numStr)):
num += chars.index(c) * (charsLen ** i)
return num