decrypt.scm 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. (library (decrypt)
  2. (export decrypt-u8 decrypt-file)
  3. (import
  4. (except (rnrs base) let-values)
  5. (only (guile)
  6. lambda* λ
  7. error
  8. eof-object?
  9. simple-format
  10. current-output-port
  11. current-input-port
  12. call-with-output-string
  13. remainder)
  14. (prefix (logging) log:)
  15. (ice-9 binary-ports)
  16. (ice-9 textual-ports)))
  17. (define decrypt-u8
  18. (λ (u8 pos secret-vector payload-offset)
  19. "Decrypt a character based on its position, a payload offset, and secret. "
  20. (let* ([key-length (vector-length secret-vector)]
  21. [pos-in-key
  22. ;; For each byte to decrypt use one character of the secret. Go back
  23. ;; to the first character of the secret again, when the key has no
  24. ;; more characters left. Alternative explanation: Use the secret as
  25. ;; a ring.
  26. (remainder (- pos payload-offset) key-length)])
  27. ;; Output a decrypted character.
  28. (integer->char
  29. ;; substract from the encrypted u8 or byte the byte of the corresponding
  30. ;; character of the secret.
  31. (- u8
  32. (vector-ref secret-vector pos-in-key))))))
  33. (define decrypt-file
  34. (lambda* (#:optional (fport (current-input-port))
  35. #:key
  36. (secret "odBearBecauseHeIsVeryGoodSiuHungIsAGo")
  37. ;; for some reason (obfuscation?) the first 123 bytes are
  38. ;; trash
  39. (num-ignored-bytes 123)
  40. (verbose #f))
  41. "Provided a file port, read byte after byte, decrypting
  42. them, until all bytes are decrypted and the file ends."
  43. (let ([secret-vector
  44. (list->vector
  45. (map char->integer
  46. (string->list secret)))])
  47. ;; Write decrypted bytes to a string, avoiding using string-append for
  48. ;; each character.
  49. (call-with-output-string
  50. (λ (string-port)
  51. ;; For some reason (obfuscation of the encryption algorithm?) the
  52. ;; first n bytes of a data file are trash.
  53. (log:debug "skipping trash bytes at the start of the file")
  54. (log:debug "trash bytes:" (get-bytevector-n fport num-ignored-bytes))
  55. (let iter ([char-index num-ignored-bytes] [u8 (get-u8 fport)])
  56. (log:debug "char-index:" char-index #:verbose verbose)
  57. (cond
  58. [(eof-object? u8)
  59. (log:debug "end of file reached" #:verbose verbose)
  60. (put-string string-port "")]
  61. ;; Otherwise decrypt the character.
  62. [else
  63. (let ([decrypted-char
  64. (decrypt-u8 u8 char-index secret-vector num-ignored-bytes)])
  65. (log:debug "read u8:" u8 "character:" (integer->char u8) "decrypted:" decrypted-char #:verbose verbose)
  66. (put-char string-port decrypted-char))
  67. (iter (+ char-index 1)
  68. (get-u8 fport))])))))))