home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / chasm2.zip / ENCRYPT.ASM < prev    next >
Assembly Source File  |  1986-02-09  |  15KB  |  375 lines

  1. ;===================================================
  2. ; PROGRAM ENCRYPT    Version 3.0 by Dave Whitman
  3. ;
  4. ; Filter to encrypt/decrypt files.
  5. ;
  6. ; Syntax:  ENCRYPT [?] [/key] [<infile] [>outfile]
  7. ;
  8. ; Reads stdin, encrypts data and writes it to stdout.
  9. ; Already encrypted files will be decrypted.
  10. ;
  11. ; An optional "key" word can be specified.
  12. ; If a key is specified, it must also be used in
  13. ; decrypting the file.
  14. ;
  15. ; The ? option prints a help message.
  16. ;
  17. ; Requires DOS 2.0, will abort under earlier versions.
  18. ;====================================================
  19.  
  20. ;===============================================================
  21. ; Discussion:
  22. ;
  23. ; ENCRYPT modifies each character by XORing it with a "mask", a
  24. ; pattern of bits.  XOR has the following truth table:
  25. ;
  26. ;          XOR |  0  1   data bit
  27. ;          ----|--------
  28. ;    mask   0  |  0  1   result
  29. ;    bit    1  |  1  0   of XOR
  30. ;
  31. ; Anywhere the mask has a 0 bit, the data will be unmodified.  A
  32. ; 1 bit in the mask will invert the state of a data bit.  For
  33. ; example:
  34. ;
  35. ;             data byte: 10000001  (character "A")
  36. ;             mask byte: 11110000
  37. ;               XOR    -----------
  38. ;                        01110001  (encrypted to character "G")
  39. ;
  40. ; Aside from encryption, use XOR any time you want to flip the state
  41. ; of one or more bits.  Use a mask with 1's in the positions you
  42. ; want to flip, and 0's in positions you want left alone.
  43. ;
  44. ; XOR has the interesting property of being its own inverse.  If
  45. ; you XOR data with a mask, then XOR again with the same mask,
  46. ; you recover the original data.  Try this example, it works!
  47. ;
  48. ;         data byte: 01110001  (encrypted character "G" from above)
  49. ;         mask byte: 11110000
  50. ;         XOR       ----------
  51. ;                    10000001  (decrypted character "A")
  52. ;
  53. ; To make the encryption a little tougher to crack, ENCRYPT
  54. ; modifies the mask after each use, by performing a 1 bit rotate
  55. ; (instruction ROL, rotate left).  Since the mask is 8 bits wide,
  56. ; a total of 8 different masks are generated:
  57. ;
  58. ;                11110000 initial mask
  59. ;                11100001 rotate left one bit (note wrap-around)
  60. ;                11000011   "
  61. ;                10000111   "
  62. ;                00001111   "
  63. ;                00011110   "
  64. ;                00111100   "
  65. ;                01111000   "
  66. ;                11110000   back to initial mask
  67. ;================================================================
  68. ;============
  69. ; Equates
  70. ;============
  71.                                   ;DOS call codes
  72. @read          equ    3FH         ;read file/device
  73. @write         equ    40H         ;write file/device
  74. @dosver        equ    30H         ;get dos version
  75. @prnstr        equ    09H         ;print string
  76.  
  77. cr             equ    0DH         ;carriage return character
  78. lf             equ    0AH         ;line feed character
  79. scrambler      equ    10101010B   ;mask to scramble key
  80.  
  81. stdin          equ    0000H       ;standard input handle
  82. stdout         equ    0001H       ;standard output handle
  83.  
  84. buf_size       equ    2000        ;size of input and output buffers
  85.  
  86.                                   ;fields in program segment prefix
  87. param_count    equ     [80H]      ;number of command line characters
  88. param_area     equ     [81H]      ;command line characters
  89. mem_avail      equ     [06H]      ;memory available in segment
  90.  
  91.  
  92. main          proc    far
  93.               call    setup       ;check dos, parse options
  94.               call    process     ;encrypt data
  95.               int     20H         ;and return to dos
  96.               endp
  97.  
  98. ;======================================
  99. ; SUBROUTINE SETUP
  100. ; Checks for proper DOS, parses options
  101. ;======================================
  102. setup        proc    near
  103.  
  104.              mov     ah, @dosver     ;what dos are we under?
  105.              int     21H
  106.              cmp     al, 2           ;2.0 or over?
  107.              jae     a_mem           ;yes, skip
  108.  
  109.              mov     ah, @prnstr     ;no, bitch
  110.              mov     dx, offset(baddos)
  111.              int     21H
  112.              pop     ax              ;reset stack
  113.              int     20H             ;and exit
  114.  
  115. a_mem        mov     ax, mem_avail   ;do we have room for the buffers?
  116.              cmp     ax, buf_size*2  ;two buffers, each buf_size long
  117.              jae     a_help          ;yes, skip
  118.              mov     ah, @prnstr     ;no, bitch
  119.              mov     dx, offset(nomem)
  120.              int     21H
  121.              pop     ax              ;reset stack
  122.              int     20H             ;and exit
  123.  
  124. a_help       xor     ch,ch           ;cx <== param count (clear out ch)
  125.              mov     cl, param_count ;  "                (fill in cl)
  126.              cmp     cl, 00H         ;any params?
  127.              je      a_exit          ;return if none
  128.  
  129.              mov     di, offset(param_area)   ;scan for help request
  130.              mov     al, '?'
  131.              cld                     ;scan up, not down
  132.              repnz                   ;repeat until matched or end
  133.              scasb                   ;scan for ?
  134.              jnz     a_key           ;reached end, no match? skip
  135.              mov     ah, @prnstr     ;found ?, so print help
  136.              mov     dx, offset(help)
  137.              int     21H
  138.              pop     ax              ;pop stack
  139.              int     20H             ;and exit
  140.  
  141. a_key        mov     di, offset(param_area)   ;scan for key
  142.              xor     ch, ch           ;cx <== param count
  143.              mov     cl, param_count  ;  "
  144.              mov     al, '/'          ;key marked with "/"
  145.              cld                     ;scan up, not down
  146.              repnz                   ;repeat until matched or end
  147.              scasb                   ;scan for /
  148.              jnz     a_exit          ;reached end, no match? exit
  149.  
  150. ;=================================================================
  151. ; Here we copy the key from the command line into a buffer for use
  152. ; during encryption.  During copying, we scramble it somewhat, to
  153. ; disguise it.  During testing of earlier versions, it was noted that
  154. ; the key would be repeated many times in the encrypted text.  The problem
  155. ; is that the space character (20H) encrypts to the key character used,
  156. ; but shifted in case.  Since spaces often come in groups, the key word
  157. ; gets copied out into the output (poor security!).  Scrambling the key
  158. ; at least ensures that the key doesn't stand out like a sore thumb.
  159. ;==================================================================
  160.  
  161.              mov     si, di            ;si points to 1st char of key
  162.              mov     di, offset(key+1) ;di points to key buffer
  163.                                        ;cx has param chars left
  164.              xor     bx, bx          ;bl counts key characters
  165.                                      ;copy the mask:
  166. copy_key    lodsb                    ;get key character
  167.              cmp     al, ' '         ;terminate with space (or end of chars)
  168.              je      ck_exit
  169.              xor     al, scrambler   ;scramble key
  170.              stosb                   ;add char to key buffer
  171.              inc     bl              ;bump char count
  172.              loop    copy_key        ;and loop
  173. ck_exit      mov     key, bl         ;save count
  174.  
  175. a_exit       ret
  176.  
  177. baddos       db      cr lf 'This program requires DOS 2.0!' cr, lf, '$'
  178.  
  179. nomem        db      cr lf 'Insufficient memory, program aborted' cr lf '$'
  180.  
  181. help         db  cr lf
  182.              db  'ENCRYPT version 3.0 by D. Whitman' cr lf
  183.              db  cr lf
  184.              db  'Syntax:  ENCRYPT [?] [/key] [<infile] [>outfile]' cr lf
  185.              db  cr lf
  186.              db  'Reads stdin, encrypts data, and writes it to stdout.' cr lf
  187.              db  'If file is already encrypted, it will be decrypted.' cr lf
  188.              db  cr lf
  189.              db  'An optional "key" word can be specified.' cr lf
  190.              db  'If used, the key must also be specified when decrypting'
  191.              db  ' the file.' cr lf
  192.              db  cr lf
  193.              db  'The ? option prints this help message.' cr lf
  194.              db  cr lf
  195.              db  'Encrypted text is unintelligable, and cannot be'
  196.              db  ' decoded by simple' cr lf
  197.              db  'substitution.  However, the encryption algorithm is'
  198.              db  ' by no means unbreakable.' cr lf
  199.              db  'Encryption should not be used as a replacement for'
  200.              db  ' proper security' cr lf
  201.              db  'with extremely sensitive data.' cr lf
  202.              db  cr lf
  203.              db  'Warning: editing of encrypted files can scramble them'
  204.              db  ' beyond recovery!' cr lf
  205.              db  cr lf
  206.              db  'This program is in the public domain.' cr lf
  207.              db  '$'
  208.              endp
  209.  
  210. ;=========================================
  211. ; SUBROUTINE PROCESS
  212. ;
  213. ;   1. load input buffer
  214. ;   2. convert each char, pass to output buffer
  215. ;   3. dump output buffer
  216. ;   4. repeat until EOF
  217. ;==========================================
  218.  
  219. process proc    near
  220.  
  221.        mov     di, offset(buf_out) ;point to output buffer
  222.        movw    outnum, 0           ;output buffer is empty
  223.        mov     bx,  0001H          ;bx holds current offset in key buffer
  224.        call    fillbuf             ;load input buffer
  225.        cmp     cx, 0000H           ;any characters available?
  226.        je      p_exit              ;nope, exit
  227.  
  228. p1     call    getchar             ;get next char in al
  229.        jc      p_done              ;carry flag set means none available
  230.        call    getkey              ;get a key character in dl
  231.        xor     al, dl              ;encrypt character
  232.        call    putchar             ;output character
  233.        jmps    p1                  ;and loop till done
  234.  
  235. p_done cmpw    outnum, 0           ;input done.  any outstanding output?
  236.        jle     p_exit              ;nope, exit
  237.        call    dumpbuf             ;yes, empty buffer
  238.  
  239. p_exit ret
  240.        endp
  241.  
  242. ;======================================================
  243. ; SUBROUTINE GETCHAR
  244. ;
  245. ; Trys to get a character from the input buffer.
  246. ; If sucessful, returns with character in AL, and carry
  247. ; flag clear.  If unsucessful, sets zero flag.
  248. ;======================================================
  249. getchar proc   near
  250.         cmp    cx, 0000           ;is the buffer empty?
  251.         jne    g1                 ;nope, skip
  252.         call   fillbuf            ;if so, try to refill it
  253.         cmp    cx, 0000           ;still empty?
  254.         je     g_abort            ;then return failure
  255.  
  256. g1      lodsb                     ;get character from [si]
  257.         dec    cx                 ;used up one char
  258.         clc                       ;clear flag to indicate sucess
  259.         ret                       ;and return
  260.  
  261. g_abort stc                       ;set flag for failure
  262.         ret
  263.         endp
  264.  
  265. ;======================================================
  266. ; SUBROUTINE FILLBUF
  267. ;
  268. ; Fills the input buffer from StdIn.  The number of
  269. ; available characters is stored in CX, and SI is reset
  270. ; to the beginning of the buffer.
  271. ;======================================================
  272. fillbuf proc   near
  273.         push    bx                  ;save position in key buffer
  274.         mov     ah, @read           ;read
  275.         mov     bx, stdin           ;from stdin
  276.         mov     cx, buf_size        ;one buffer's worth
  277.         mov     dx, offset(buf_in)  ;into the input buffer
  278.         int     21H
  279.         mov     cx, ax              ;save number of chars read
  280.         mov     si, offset(buf_in)  ;reset buffer
  281.         pop     bx                  ;restore key buffer position
  282.         ret
  283.         endp
  284.  
  285. ;==================================================
  286. ; SUBROUTINE GETKEY
  287. ;
  288. ; Gets a key byte from the key buffer.  The byte
  289. ; is returned in DL.
  290. ;
  291. ; Each character from the key word is used sucessively.
  292. ; To maximize confusion, the byte is rotated before each use.
  293. ;====================================================
  294.  
  295. getkey  proc    near
  296.         mov     dl, offset(key)[bx]  ;get key byte
  297.         rolb    offset(key)[bx]      ;rotate it for next use
  298.         inc     bl                   ;point to next character
  299.         cmp     bl, key              ;have we run out of characters?
  300.         jle     gk_exit              ;nope, exit
  301.         mov     bl, 01H              ;yes, start back at beginning
  302. gk_exit ret
  303.         endp
  304.  
  305. ;===================================================
  306. ; SUBROUTINE PUTCHAR
  307. ;
  308. ; Moves the character in AL into the output buffer.
  309. ; If the buffer is now full, it is dumped to disk.
  310. ;===================================================
  311.  
  312. putchar proc near
  313.         stosb                   ;move character into buffer
  314.         incw  outnum            ;bump count of chars in buffer
  315.         cmpw  outnum, buf_size  ;is buffer full?
  316.         jl    pu_exit           ;no, skip
  317.         call  dumpbuf           ;yes, dump buffer to disk
  318. pu_exit ret
  319.         endp
  320.  
  321. ;==================================================
  322. ; SUBROUTINE DUMPBUF
  323. ;
  324. ; Dumps the output buffer to StdOut.
  325. ;==================================================
  326. dumpbuf proc near
  327.         push    ax                   ;save active registers
  328.         push    bx                   ; "      "      "
  329.         push    cx                   ; "      "      "
  330.         push    dx                   ; "      "      "
  331.         mov     ah, @write           ;write
  332.         mov     bx, stdout           ;to stdout
  333.         mov     cx, outnum           ;number of chars for output
  334.         mov     dx, offset(buf_out)  ;from output buffer
  335.         int     21H
  336.         movw    outnum, 0            ;reset buffer
  337.         mov     di, offset(buf_out)  ;  "     "
  338.         pop     dx                   ;restore active registers
  339.         pop     cx                   ;   "       "       "
  340.         pop     bx                   ;   "       "       "
  341.         pop     ax                   ;   "       "       "
  342.         ret
  343.         endp
  344.  
  345. ;=================
  346. ;GLOBAL VARIABLES
  347. ;=================
  348. outnum     dw  0000H     ;number of characters in output buffer
  349.  
  350. ;=====================================================
  351. ;BUFFERS
  352. ;
  353. ; No space is actually allocated for the buffers.
  354. ; At run time, the program checks to ensure there
  355. ; is suffcient free memory, then uses the memory
  356. ; immediately after itself for buffers.
  357. ;
  358. ; This stratagy minimizes the size of the object file,
  359. ; and lets the program load quicker.
  360. ;======================================================
  361.  
  362. key       db  01H                 ;number of characters in key
  363.           db  01H                 ;key text
  364.           ds  128                 ; "   "
  365.  
  366. buf_in
  367.  
  368.           org offset($+buf_size)   ;this is a trick to set the address
  369.                                    ;the output buffer.
  370.                                    ;the address of buf_out is set to be
  371.                                    ;the offset of the input buffer, plus
  372.                                    ;the buffer length.
  373.  
  374. buf_out                            ;output buffer
  375.