How would I go about circle left shifting every character in a string by the corresponding character in a 'password' string.
char *shift_encrypt(char *plaintext, char *password) {
for (int i = 0; plaintext[i] != '\0'; i++) {
plaintext[i] = (plaintext[i] << password[i]) | (plaintext[i] >> (8 - password[i]));
}
return plaintext;
}
EDIT: To clarify what I am asking, if I wanted to circle shift for example the character 'A' by the character 'p', I mean something along the lines of:
0100 0001 ('A') << 0x70 ('p') shown bit-shifted left bit by bit
1. 1000 0010
2. 0000 0101
.
.
.
110. 0101 0000
111. 1010 0000
112. 0100 0001
So basically shifting by 1, 126 times?
To circular shift an 8-bit object with large values like 112 ('p'
), mod the shift by 8u
. %
with a negative char
and 8 is not mod so use unsigned math.
Access plaintext[i]
as an unsigned char []
to avoid sign extension on right shifts.
Use size_t
to index string to handle even very long strings.
Sample fix:
char *shift_encrypt2(char *plaintext, const char *password) {
unsigned char *uplaintext = (unsigned char *) plaintext;
for (size_t i = 0; uplaintext[i]; i++) {
unsigned shift = password[i] % 8u;
uplaintext[i] = (uplaintext[i] << shift) | (uplaintext[i] >> (8u - shift));
}
return plaintext;
}
Note: if the password
string is shorter than than plaintext
string, we have trouble. A possible fix would re-cycle through the password[]
.
Advanced: use restrict
to allow the compiler to assume plaintext[]
and password[]
do not overlap and emit potentially faster code.
char *shift_encrypt2(char * restrict plaintext, const char * restrict password) {
Advanced: Code really should access password[]
as an unsigned char
array too, yet with common and ubiquitous 2's compliment, password[i] % 8u
makes no difference.
char *shift_encrypt3(char * restrict plaintext, const char * restrict password) {
if (password[0]) {
unsigned char *uplaintext = (unsigned char *) plaintext;
const unsigned char *upassword = (const unsigned char *) password;
for (size_t i = 0; uplaintext[i]; i++) {
if (*upassword == 0) {
upassword = (const unsigned char *) password;
}
unsigned shift = *upassword++ % 8u;
uplaintext[i] = (uplaintext[i] << shift) | (uplaintext[i] >> (8u - shift));
}
}
return plaintext;
}