I am trying to run an encryption algorithm that takes an input message, breaks it up into blocks of four characters, moves "x" bits from the front to the back, and then converts it back into four scrambled characters. I believe that this is called a block-shift cipher, although I am not quite sure. The program can encrypt and decrypt perfectly fine when running in Python. However, after converting the code, by hand, into JavaScript, I was getting some strange results from the String.fromCharCode method. To put it quite simply, the JavaScript method is returning more characters, specifically "" characters, than Python is, even when the message and key are being kept the same. I would appreciate any help for how to solve this problem and what exactly the problem is.
This code is for a tool that I am developing, and I need to get it completed as fast as possible. I have already tried converting the JavaScript character encodings into "UTF-8" using the utf8 module from the Node Package Manager, to no avail. I double-checked my code several times, and, other than the character converting, the Python and JavaScript code are doing the same thing, and are producing the same numbers and values. In the below code, the problems I am mentioning are originating from the "reconstructMsg" function in the JavaScript code.
// JavaScript:
import integerBitLength from 'integer-bit-length';
// Function to break message into chunks
function chunkMsg(message, chunkSize = 4) {
// Create an array to store the chunks
let msgChunks = [];
// Control
let chunk = 0,
chunkCount = Math.floor(message.length / chunkSize) + 1;
// Iterate through the message
for (let num of [
...Array(chunkCount * chunkSize).keys()
]) {
// Make room for the next chunk's number
chunk = chunk << 8;
// Make sure that 'num' is within the length of 'message'
if (num < message.length) chunk += message[num].charCodeAt(0);
// Check if there are the ascii values of four characters in the chunk
if (integerBitLength(chunk) > (chunkSize - 1) * 8) {
// Append chunk
msgChunks.push(chunk);
// Reset chunk
chunk = 0;
}
}
// Return the chunk array
return msgChunks;
}
// Function to reconstruct message
function reconstructMsg(chunks, chunkSize = 4) {
// Empty message
let msg = '';
// Iterate through all of the chunks
for (let i = 0; i < chunks.length; i++) {
let chunk = chunks[i];
// Loop through each chunk
for (let j = 0; j < chunkSize; j++) {
// NOTES on the below code
// (8 * (chunk_size - 1 - j)) is the number of bits to chop off of the end
// (chunk >> <above_code>) chops the number of bits above off of the chunk
// <above_code> % 2 ** 8 takes only the first 8 bits from the above code
// because 2 ** 8 = 256
// the modulo function (x % y) can have a max value of "y - 1" and 8 bits can have a max value of 255
// In other words, because everything above the 8th bit is a multiple of 256, we ignore them
let number = (chunk >>> (8 * (chunkSize - 1 - j))) % 2 ** 8;
// Add the character with the above keycode to the message
msg += String.fromCharCode(number);
}
}
// Return the message
return msg;
}
// Function to encrypt chunks in a message
function encryptMsg(chunks, key, chunkSize = 4) {
// List of encrypted chunks
let cipherList = [];
// Set the maximum amount of bits
let bitCount = chunkSize * 8;
// Iterate through the chunks
for (let i of [
...Array(chunks.length).keys()
]) {
// Set chunk
let chunk = chunks[i];
// Set the bits to carry
let carry = chunk % 2 ** key;
// Make room for the remaining bits to be places at the end
carry = (carry << (bitCount - key)) >>> 0;
// Combine the shifted characters
let cipher = (chunk >>> key) + carry;
// Add cipher
cipherList.push(cipher);
}
// Return the cipher list
return cipherList;
}
# Python:
# Function to chunk message into sets of 32-bits
def chunk_msg(msg, chunk_size=4):
# Create a list to store the chunks
msg_chunks = []
# Control variables
chunk = 0
chunk_count = len(msg) // chunk_size + 1
# Iterate through the message
for i in range(chunk_count * chunk_size):
# Make room for the next character's number
chunk = chunk << 8
# Make sure that i is within the length of the function
if i < len(msg):
chunk += ord(msg[i])
# If the chunk has 4 characters in their ascii encoding, save the chunk
if chunk.bit_length() > (chunk_size - 1) * 8:
msg_chunks.append(chunk)
chunk = 0
# Return the chunks
return msg_chunks
# Function to reconstruct message
def reconstruct_msg(chunks, chunk_size=4):
# Empty message
msg = ""
# Iterate through all of the chunks
for i in range(len(chunks)):
chunk = chunks[i]
# Loop through each chunk
for j in range(chunk_size):
# NOTES on the below code
# (8 * (chunk_size - 1 - j)) is the number of bits to chop off of the end
# (chunk >> <above_code>) chops the number of bits above off of the chunk
# <above_code> % 2 ** 8 takes only the first 8 bits from the above code
# because 2 ** 8 = 256
# the modulo function (x % y) can have a max value of "y - 1" and 8 bits can have a max value of 255
# In other words, because everything above the 8th bit is a multiple of 256, we ignore them
number = (chunk >> (8 * (chunk_size - 1 - j))) % 2**8
print(number)
# Add the character with the above keycode to the message
msg += chr(number)
print(f"\n\n{chr(number)}")
# Return the message
return msg
# Function to encrypt chunks
def apply_rotate(msg_list, key, chunk_size=4):
cipher_list = []
# Set the maximum amount of bits
bit_count = chunk_size * 8
# Iterate through each message chunk
for i in range(len(msg_list)):
# Set chunk
chunk = msg_list[i]
print(chunk)
# Set the bits to carry
carry = chunk % (2**key)
# Make room for the remaining bits to be placed on the end
carry = carry << (bit_count - key)
# Combine the shifted characters into a variable
cipher = (chunk >> key) + carry
# Add the encoded chunk to the list
cipher_list.append(cipher)
print(cipher_list)
# Return the cipher list
return cipher_list
When the above functions are run in the order: chunkMsg, encryptMsg, and reconstructMsg, with a message of "Hello" and a key of 12, Python produces the correct string, "ÆÄV ð", while JavaScript produces, the incorrect string, "ÆÄVð" (There are undefined characters between the Ä and the V, the V and the ð, and the ð and the end of the message. They may not show up in the question once it is posted).
Once again, I would deeply appreciate any help in this matter and apologize if the question is a little lengthy.