The following is come code I found I wrote many years ago in Digital VAX MACRO to check passwords for a particular username against a dictionary of words concatenated with a number.
.title check_password
$rmsdef
$uaidef
.psect rw_data rd,wrt,noexe,noshr,long
pwdlist_fab: $fab fnm = <sys$library:VMS$PASSWORD_DICTIONARY.DATA>
pwdlist_rab: $rab fab = pwdlist_fab,-
rop = rah,-
ubf = rec_buff,-
usz = rec_size
rec_size = 32
rec_desc: .word rec_size
.word 0
.address rec_buff
rec_buff: .blkb rec_size
cur_count: .long
max_count = 99
num_size = 2
cur_no: .ascid \99\
cur_pwd: .word rec_size+num_size
.word 0
.address 10$
10$: .blkb rec_size+num_size
cur_hash: .blkb 8
username:
username_len: .word 12
.word 0
.address 10$
10$: .blkb 12
pwd_list: .word 1
.word uai$_encrypt
.address encrypt
.address encrypt_len
.word 8
.word uai$_pwd
.address pwd
.address pwd_len
.word 2
.word uai$_salt
.address salt
.address salt_len
.word 0
.word 0
encrypt: .byte
encrypt_len: .word
pwd: .blkb 8
pwd_len: .word
salt: .word
salt_len: .word
usage_msg: .ascid \VMS username must be specificed as a parameter\
.psect code rd,nowrt,exe,shr,long
.entry check_password,^m<>
; get username passed on command line - display error if not present
pushaq username
calls #1,g^lib$get_foreign
blbc r0,error_exit
pushaw username_len
pushaq username
pushaq username
calls #3,g^str$trim
blbc r0,error_exit
tstw username_len
bnequ get_pwd
pushaq usage_msg
calls #1,g^lib$put_output
brb normal_exit
; retrieve the hashed password from the UAF file
get_pwd: $getuai_s usrnam=username,-
itmlst=pwd_list
blbc r0,error_exit
; open the VMS password dictionary
open_dic: $open fab=pwdlist_fab
blbc r0,error_exit
$connect rab=pwdlist_rab
blbc r0,error_exit
; retrieve a word from the dictionary
word_loop: $get rab=pwdlist_rab
blbs r0,remove_nulls
cmpl r0,#rms$_eof
beql normal_exit
brb error_exit
; get rid of nulls on the end of the record and convert to uppercase
remove_nulls: clrw r1
movaq rec_buff,r2
10$: tstb (r2)
beql 20$
incw r1
incl r2
brb 10$
20$: movw r1,rec_desc
pushaq rec_desc
pushaq rec_desc
calls #2,g^str$upcase
; start back at zero for new word
clrl cur_count
; append a number to the word
append_no: pushl #2
pushl #1
pushaq cur_no
pushal cur_count
calls #4,g^ots$cvt_l_tu
movw #rec_size+num_size,cur_pwd
pushaq cur_no
pushaq rec_desc
pushaq cur_pwd
calls #3,g^str$concat
blbc r0,error_exit
pushaw cur_pwd
pushaq cur_pwd
pushaq cur_pwd
calls #3,g^str$trim
; now we have all the info to hash a password
$hash_password_s -
pwd=cur_pwd,-
alg=encrypt,-
salt=salt,-
usrnam=username,-
hash=cur_hash
blbc r0,error_exit
; check if we have a match on the hashed password - if so display
cmpl cur_hash,pwd
bneq no_match
cmpl cur_hash+4,pwd+4
bneq no_match
pushaq cur_pwd
calls #1,g^lib$put_output
brb normal_exit
; loop back 'max_count' times
no_match: aoblss #max_count,cur_count,append_no
; loop back for another word
brb word_loop
normal_exit: movl #1,r0
error_exit: ret
.end check_password