home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Share Gallery 1
/
share_gal_1.zip
/
share_gal_1
/
LA
/
LA001.ZIP
/
CHASM.ARC
/
ENCRYPT.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-02-09
|
15KB
|
375 lines
;===================================================
; PROGRAM ENCRYPT Version 3.0 by Dave Whitman
;
; Filter to encrypt/decrypt files.
;
; Syntax: ENCRYPT [?] [/key] [<infile] [>outfile]
;
; Reads stdin, encrypts data and writes it to stdout.
; Already encrypted files will be decrypted.
;
; An optional "key" word can be specified.
; If a key is specified, it must also be used in
; decrypting the file.
;
; The ? option prints a help message.
;
; Requires DOS 2.0, will abort under earlier versions.
;====================================================
;===============================================================
; Discussion:
;
; ENCRYPT modifies each character by XORing it with a "mask", a
; pattern of bits. XOR has the following truth table:
;
; XOR | 0 1 data bit
; ----|--------
; mask 0 | 0 1 result
; bit 1 | 1 0 of XOR
;
; Anywhere the mask has a 0 bit, the data will be unmodified. A
; 1 bit in the mask will invert the state of a data bit. For
; example:
;
; data byte: 10000001 (character "A")
; mask byte: 11110000
; XOR -----------
; 01110001 (encrypted to character "G")
;
; Aside from encryption, use XOR any time you want to flip the state
; of one or more bits. Use a mask with 1's in the positions you
; want to flip, and 0's in positions you want left alone.
;
; XOR has the interesting property of being its own inverse. If
; you XOR data with a mask, then XOR again with the same mask,
; you recover the original data. Try this example, it works!
;
; data byte: 01110001 (encrypted character "G" from above)
; mask byte: 11110000
; XOR ----------
; 10000001 (decrypted character "A")
;
; To make the encryption a little tougher to crack, ENCRYPT
; modifies the mask after each use, by performing a 1 bit rotate
; (instruction ROL, rotate left). Since the mask is 8 bits wide,
; a total of 8 different masks are generated:
;
; 11110000 initial mask
; 11100001 rotate left one bit (note wrap-around)
; 11000011 "
; 10000111 "
; 00001111 "
; 00011110 "
; 00111100 "
; 01111000 "
; 11110000 back to initial mask
;================================================================
;============
; Equates
;============
;DOS call codes
@read equ 3FH ;read file/device
@write equ 40H ;write file/device
@dosver equ 30H ;get dos version
@prnstr equ 09H ;print string
cr equ 0DH ;carriage return character
lf equ 0AH ;line feed character
scrambler equ 10101010B ;mask to scramble key
stdin equ 0000H ;standard input handle
stdout equ 0001H ;standard output handle
buf_size equ 2000 ;size of input and output buffers
;fields in program segment prefix
param_count equ [80H] ;number of command line characters
param_area equ [81H] ;command line characters
mem_avail equ [06H] ;memory available in segment
main proc far
call setup ;check dos, parse options
call process ;encrypt data
int 20H ;and return to dos
endp
;======================================
; SUBROUTINE SETUP
; Checks for proper DOS, parses options
;======================================
setup proc near
mov ah, @dosver ;what dos are we under?
int 21H
cmp al, 2 ;2.0 or over?
jae a_mem ;yes, skip
mov ah, @prnstr ;no, bitch
mov dx, offset(baddos)
int 21H
pop ax ;reset stack
int 20H ;and exit
a_mem mov ax, mem_avail ;do we have room for the buffers?
cmp ax, buf_size*2 ;two buffers, each buf_size long
jae a_help ;yes, skip
mov ah, @prnstr ;no, bitch
mov dx, offset(nomem)
int 21H
pop ax ;reset stack
int 20H ;and exit
a_help xor ch,ch ;cx <== param count (clear out ch)
mov cl, param_count ; " (fill in cl)
cmp cl, 00H ;any params?
je a_exit ;return if none
mov di, offset(param_area) ;scan for help request
mov al, '?'
cld ;scan up, not down
repnz ;repeat until matched or end
scasb ;scan for ?
jnz a_key ;reached end, no match? skip
mov ah, @prnstr ;found ?, so print help
mov dx, offset(help)
int 21H
pop ax ;pop stack
int 20H ;and exit
a_key mov di, offset(param_area) ;scan for key
xor ch, ch ;cx <== param count
mov cl, param_count ; "
mov al, '/' ;key marked with "/"
cld ;scan up, not down
repnz ;repeat until matched or end
scasb ;scan for /
jnz a_exit ;reached end, no match? exit
;=================================================================
; Here we copy the key from the command line into a buffer for use
; during encryption. During copying, we scramble it somewhat, to
; disguise it. During testing of earlier versions, it was noted that
; the key would be repeated many times in the encrypted text. The problem
; is that the space character (20H) encrypts to the key character used,
; but shifted in case. Since spaces often come in groups, the key word
; gets copied out into the output (poor security!). Scrambling the key
; at least ensures that the key doesn't stand out like a sore thumb.
;==================================================================
mov si, di ;si points to 1st char of key
mov di, offset(key+1) ;di points to key buffer
;cx has param chars left
xor bx, bx ;bl counts key characters
;copy the mask:
copy_key lodsb ;get key character
cmp al, ' ' ;terminate with space (or end of chars)
je ck_exit
xor al, scrambler ;scramble key
stosb ;add char to key buffer
inc bl ;bump char count
loop copy_key ;and loop
ck_exit mov key, bl ;save count
a_exit ret
baddos db cr lf 'This program requires DOS 2.0!' cr, lf, '$'
nomem db cr lf 'Insufficient memory, program aborted' cr lf '$'
help db cr lf
db 'ENCRYPT version 3.0 by D. Whitman' cr lf
db cr lf
db 'Syntax: ENCRYPT [?] [/key] [<infile] [>outfile]' cr lf
db cr lf
db 'Reads stdin, encrypts data, and writes it to stdout.' cr lf
db 'If file is already encrypted, it will be decrypted.' cr lf
db cr lf
db 'An optional "key" word can be specified.' cr lf
db 'If used, the key must also be specified when decrypting'
db ' the file.' cr lf
db cr lf
db 'The ? option prints this help message.' cr lf
db cr lf
db 'Encrypted text is unintelligable, and cannot be'
db ' decoded by simple' cr lf
db 'substitution. However, the encryption algorithm is'
db ' by no means unbreakable.' cr lf
db 'Encryption should not be used as a replacement for'
db ' proper security' cr lf
db 'with extremely sensitive data.' cr lf
db cr lf
db 'Warning: editing of encrypted files can scramble them'
db ' beyond recovery!' cr lf
db cr lf
db 'This program is in the public domain.' cr lf
db '$'
endp
;=========================================
; SUBROUTINE PROCESS
;
; 1. load input buffer
; 2. convert each char, pass to output buffer
; 3. dump output buffer
; 4. repeat until EOF
;==========================================
process proc near
mov di, offset(buf_out) ;point to output buffer
movw outnum, 0 ;output buffer is empty
mov bx, 0001H ;bx holds current offset in key buffer
call fillbuf ;load input buffer
cmp cx, 0000H ;any characters available?
je p_exit ;nope, exit
p1 call getchar ;get next char in al
jc p_done ;carry flag set means none available
call getkey ;get a key character in dl
xor al, dl ;encrypt character
call putchar ;output character
jmps p1 ;and loop till done
p_done cmpw outnum, 0 ;input done. any outstanding output?
jle p_exit ;nope, exit
call dumpbuf ;yes, empty buffer
p_exit ret
endp
;======================================================
; SUBROUTINE GETCHAR
;
; Trys to get a character from the input buffer.
; If sucessful, returns with character in AL, and carry
; flag clear. If unsucessful, sets zero flag.
;======================================================
getchar proc near
cmp cx, 0000 ;is the buffer empty?
jne g1 ;nope, skip
call fillbuf ;if so, try to refill it
cmp cx, 0000 ;still empty?
je g_abort ;then return failure
g1 lodsb ;get character from [si]
dec cx ;used up one char
clc ;clear flag to indicate sucess
ret ;and return
g_abort stc ;set flag for failure
ret
endp
;======================================================
; SUBROUTINE FILLBUF
;
; Fills the input buffer from StdIn. The number of
; available characters is stored in CX, and SI is reset
; to the beginning of the buffer.
;======================================================
fillbuf proc near
push bx ;save position in key buffer
mov ah, @read ;read
mov bx, stdin ;from stdin
mov cx, buf_size ;one buffer's worth
mov dx, offset(buf_in) ;into the input buffer
int 21H
mov cx, ax ;save number of chars read
mov si, offset(buf_in) ;reset buffer
pop bx ;restore key buffer position
ret
endp
;==================================================
; SUBROUTINE GETKEY
;
; Gets a key byte from the key buffer. The byte
; is returned in DL.
;
; Each character from the key word is used sucessively.
; To maximize confusion, the byte is rotated before each use.
;====================================================
getkey proc near
mov dl, offset(key)[bx] ;get key byte
rolb offset(key)[bx] ;rotate it for next use
inc bl ;point to next character
cmp bl, key ;have we run out of characters?
jle gk_exit ;nope, exit
mov bl, 01H ;yes, start back at beginning
gk_exit ret
endp
;===================================================
; SUBROUTINE PUTCHAR
;
; Moves the character in AL into the output buffer.
; If the buffer is now full, it is dumped to disk.
;===================================================
putchar proc near
stosb ;move character into buffer
incw outnum ;bump count of chars in buffer
cmpw outnum, buf_size ;is buffer full?
jl pu_exit ;no, skip
call dumpbuf ;yes, dump buffer to disk
pu_exit ret
endp
;==================================================
; SUBROUTINE DUMPBUF
;
; Dumps the output buffer to StdOut.
;==================================================
dumpbuf proc near
push ax ;save active registers
push bx ; " " "
push cx ; " " "
push dx ; " " "
mov ah, @write ;write
mov bx, stdout ;to stdout
mov cx, outnum ;number of chars for output
mov dx, offset(buf_out) ;from output buffer
int 21H
movw outnum, 0 ;reset buffer
mov di, offset(buf_out) ; " "
pop dx ;restore active registers
pop cx ; " " "
pop bx ; " " "
pop ax ; " " "
ret
endp
;=================
;GLOBAL VARIABLES
;=================
outnum dw 0000H ;number of characters in output buffer
;=====================================================
;BUFFERS
;
; No space is actually allocated for the buffers.
; At run time, the program checks to ensure there
; is suffcient free memory, then uses the memory
; immediately after itself for buffers.
;
; This stratagy minimizes the size of the object file,
; and lets the program load quicker.
;======================================================
key db 01H ;number of characters in key
db 01H ;key text
ds 128 ; " "
buf_in
org offset($+buf_size) ;this is a trick to set the address
;the output buffer.
;the address of buf_out is set to be
;the offset of the input buffer, plus
;the buffer length.
buf_out ;output buffer