Thanks for @LeFF to discovering that thread, with it the code becomes: import macros type estring = distinct string proc `xor`*(x, y: char): char {.magic: "BitxorI", noSideEffect.} proc fnv32a*[T: string|openArray[char]|openArray[uint8]|openArray[int8]](data: T): int32 = result = -18652613'i32 for b in items(data): result = result xor int32(ord(b)) result = result *% 16777619 proc decodeStr*(s: estring, key: int32): string = var s = string(s) var k = key result = newString(s.len) for i in s.low .. s.high: result[i] = s[i] result[i] = result[i] xor chr(uint8(k and 0xFF)) result[i] = result[i] xor chr(uint8((k shr 8) and 0xFF)) result[i] = result[i] xor chr(uint8((k shr 16) and 0xFF)) result[i] = result[i] xor chr(uint8((k shr 24) and 0xFF)) k = k +% 1 proc encodeStr*(s: string, key: int32): estring = estring(decodeStr(estring(s), key)) var encodedCounter {.compiletime.}: int32 = fnv32a(CompileTime & CompileDate) and 0x7FFFFFFF # term rewriting macro macro encrypt*{s}(s: string{lit}): untyped = var encodedStr = encodeStr($s, encodedCounter) result = quote do: decodeStr(estring(`encodedStr`), `encodedCounter`) encodedCounter = (encodedCounter *% 16777619) and 0x7FFFFFFF # test-case echo "hello" Run
Or you could even import this code from other modules and all string literals in them will automatically get encrypted :)