Skip to content

ciphers/xor_cipher: XORCipher leaves newline-class characters un-encrypted (regex /./g skips line terminators) #308

@aimasteracc

Description

@aimasteracc

Describe the bug

ciphers/xor_cipher.ts::XORCipher skips line-terminator characters, leaving them un-encrypted. It applies the cipher with str.replace(/./g, ...), but in JavaScript . (without the s / dotAll flag) does not match line terminators — \n (U+000A), \r (U+000D), , . Those characters are passed through unchanged instead of being XORed with the key.

export const XORCipher = (str: string, key: number): string =>
  str.replace(/./g, (char: string) =>
    String.fromCharCode(char.charCodeAt(0) ^ key)
  )

The docstring says "Each character is bitwise XORed with the key … We loop through the input string, XORing each character", but newline-class characters are not XORed.

To Reproduce

const enc = XORCipher("A\nB", 1)
// input char codes: [65, 10, 66]
// enc   char codes: [64, 10, 67]   <- 10 (\n) should be 11 (10 ^ 1)

The 'A' (65→64) and 'B' (66→67) are XORed, but '\n' (10) stays 10 instead of becoming 11.

Expected behavior

Every character — including \n, \r, , — is XORed with the key, so XORCipher("A\nB", 1) yields char codes [64, 11, 67].

Actual behavior

Line-terminator characters are left unchanged, so the "encrypted" output still contains the original newlines (an information leak, and the output is not a correct XOR of the input).

Suggested fix

Don't rely on the dot-matches-everything assumption. Either add the dotAll flag (/./gs) or, more robustly, map over code points directly:

export const XORCipher = (str: string, key: number): string =>
  Array.from(str, (char) => String.fromCharCode(char.charCodeAt(0) ^ key)).join('')

(The Array.from form also avoids the regex entirely.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions