| 34 | | As you can see from this table, both OpenVista and WorldVistA have done badly (it's not known whether the OpenVista version is even legal) while vxVista has done the best. |
| | 34 | As you can see from this table, both OpenVista and WorldVistA have done badly (it's not known whether the OpenVista version is even legal) while vxVista has done the best. |
| | 35 | |
| | 36 | == A solution to hashing and encryption on GT.M == |
| | 37 | I wrote this routine to replace XUSHSHP: |
| | 38 | {{{ |
| | 39 | UJOSHSHP ; VEN/SMH - Encrypt Data a la XUSHSHP ;2013-02-27 9:44 AM |
| | 40 | ;;1.0;JORDAN SPECIFIC MODIFICATIONS; |
| | 41 | ; |
| | 42 | HASH ; HASH |
| | 43 | Q:'$D(X) Q:'$L(X) |
| | 44 | ; Input: X from Symbol Table. X can be any length |
| | 45 | ; Output: X hashed, as 20 characters |
| | 46 | ; |
| | 47 | ; Use sha512 with user stuff as salt |
| | 48 | ; Should use PBKDF2, bcrypt, or scrypt; but not available in openssl CLI. |
| | 49 | S X=$$UP^XLFSTR(X) ; Uppercase X; per original VA code. |
| | 50 | N SALTED S SALTED=$P(^VA(200,DUZ,1),U,7)_X_DUZ ; Salt X with User Creation Date and DUZ. |
| | 51 | N CALL S CALL="openssl dgst -sha512" ; SHA512 OS call |
| | 52 | N DEVICE S DEVICE="hashPipe" |
| | 53 | N OUTPUT |
| | 54 | N OLDIO S OLDIO=$IO |
| | 55 | OPEN DEVICE:(shell="/bin/sh":comm=CALL)::"PIPE" |
| | 56 | USE DEVICE WRITE SALTED,/EOF READ OUTPUT:1 U OLDIO CLOSE DEVICE |
| | 57 | S X=$E(OUTPUT,$L(OUTPUT)-19,$L(OUTPUT)) ; X is the return variable; only 20 characters long |
| | 58 | QUIT |
| | 59 | ; |
| | 60 | EN ; ENCRYPT |
| | 61 | Q:'$D(X)!('$D(X1))!('$D(X2)) Q:'$L(X) |
| | 62 | ; Expect X, X1, X2 |
| | 63 | ; X is the string to encrypt. X1 and X2 are salts/password |
| | 64 | ; X1 can be the DUZ |
| | 65 | ; X2 can be the checksum of the text to encrypt |
| | 66 | ; Output: X, the encrypted string. Length is the same the input. |
| | 67 | ; Maximum supported length is maximum global node length. |
| | 68 | ; Encrypting word processing fields is not supported. |
| | 69 | ; |
| | 70 | ; AES- Cipher Block Chaining with Base 64 encoding with password w no salt. |
| | 71 | N CALL S CALL="openssl enc -a -aes-256-cbc -nosalt -pass pass:"_X1_X2 |
| | 72 | ; N CALL S CALL="openssl enc -a -des-ede3-cbc -nosalt -pass pass:"_X1_X2 |
| | 73 | ; N CALL S CALL="openssl enc -bf-cbc -nosalt -pass pass:"_X1_X2 |
| | 74 | ; N CALL S CALL="openssl enc -a -rc4 -nosalt -pass pass:"_X1_X2 |
| | 75 | N DEVICE S DEVICE="encryptionPipe" |
| | 76 | N OLDIO S OLDIO=$IO |
| | 77 | OPEN DEVICE:(shell="/bin/sh":comm=CALL)::"PIPE" |
| | 78 | USE DEVICE |
| | 79 | WRITE X,/EOF ; Write the string to encrypt |
| | 80 | N I,OUTPUT ; I = counter. OUTPUT = encyrpted tems |
| | 81 | FOR I=1:1 READ OUTPUT(I) Q:$ZEOF ; Read it into Output Array |
| | 82 | U OLDIO |
| | 83 | CLOSE DEVICE |
| | 84 | ; Next two lines: concatentate the array into the root node |
| | 85 | S OUTPUT="" |
| | 86 | F I=1:1 Q:'$D(OUTPUT(I)) S OUTPUT=OUTPUT_OUTPUT(I) K OUTPUT(I) |
| | 87 | ; X is the output from the API |
| | 88 | S X=OUTPUT |
| | 89 | QUIT |
| | 90 | ; |
| | 91 | DE ; DECRYPT |
| | 92 | Q:'$D(X)!('$D(X1))!('$D(X2)) Q:'$L(X) |
| | 93 | ; Expect X, X1, X2 |
| | 94 | ; X is the string to encrypt. X1 and X2 are salts/password |
| | 95 | ; X1 can be the DUZ |
| | 96 | ; X2 can be the checksum of the text to encrypt |
| | 97 | ; Output: X, the decrypted string. Length is the same the input. |
| | 98 | ; Maximum supported length is maximum global node length. |
| | 99 | ; Encrypting word processing fields is not supported. |
| | 100 | N CALL S CALL="openssl enc -d -a -aes-256-cbc -nosalt -pass pass:"_X1_X2 |
| | 101 | ; N CALL S CALL="openssl enc -a -d -rc4 -nosalt -pass pass:"_X1_X2 |
| | 102 | N DEVICE S DEVICE="decryptionPipe" |
| | 103 | N OLDIO S OLDIO=$IO |
| | 104 | OPEN DEVICE:(shell="/bin/sh":comm=CALL)::"PIPE" |
| | 105 | USE DEVICE |
| | 106 | F W $E(X,1,64),! S X=$E(X,65,1024*1024*1024) Q:X="" ; Write Input base64 style |
| | 107 | WRITE /EOF |
| | 108 | N OUTPUT R OUTPUT:1 ; Read Output of decryption back. |
| | 109 | U OLDIO |
| | 110 | CLOSE DEVICE |
| | 111 | S X=OUTPUT ; X is output |
| | 112 | QUIT |
| | 113 | ; |
| | 114 | RUNTESTS S IO=$P S DIQUIET=1 D DT^DICRW D:$L($T(EN^XTMUNIT)) EN^XTMUNIT($T(+0),1) QUIT |
| | 115 | THASH ; @TEST - Test Hashing |
| | 116 | N DUZ |
| | 117 | S DUZ=1 N X S X="HELLO WORLD" D HASH |
| | 118 | N RESULT1 S RESULT1=X |
| | 119 | S DUZ=1 N X S X="HELLO WORLD" D HASH |
| | 120 | N RESULT2 S RESULT2=X |
| | 121 | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results are not equal") |
| | 122 | ; |
| | 123 | S DUZ=1 N X S X="HELLO WORLD" D HASH |
| | 124 | N RESULT1 S RESULT1=X |
| | 125 | S DUZ=2 N X S X="HELLO WORLD" D HASH |
| | 126 | N RESULT2 S RESULT2=X |
| | 127 | D CHKTF^XTMUNIT(RESULT1'=RESULT2,"Hash results are not supposed to be equal") |
| | 128 | ; |
| | 129 | S DUZ=1 |
| | 130 | N X S X="Hello World" D HASH |
| | 131 | N RESULT1 S RESULT1=X |
| | 132 | N X S X="HELLO WORLD" D HASH |
| | 133 | N RESULT2 S RESULT2=X |
| | 134 | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results of different cases aren't equal") |
| | 135 | QUIT |
| | 136 | ; |
| | 137 | THASH2 ; @TEST - Test Hashing using main calling routine XUSHSHP |
| | 138 | N DUZ |
| | 139 | S DUZ=1 N X S X="HELLO WORLD" D HASH^XUSHSHP |
| | 140 | N RESULT1 S RESULT1=X |
| | 141 | S DUZ=1 N X S X="HELLO WORLD" D HASH^XUSHSHP |
| | 142 | N RESULT2 S RESULT2=X |
| | 143 | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results are not equal") |
| | 144 | ; |
| | 145 | S DUZ=1 N X S X="HELLO WORLD" D HASH^XUSHSHP |
| | 146 | N RESULT1 S RESULT1=X |
| | 147 | S DUZ=2 N X S X="HELLO WORLD" D HASH^XUSHSHP |
| | 148 | N RESULT2 S RESULT2=X |
| | 149 | D CHKTF^XTMUNIT(RESULT1'=RESULT2,"Hash results are not supposed to be equal") |
| | 150 | ; |
| | 151 | S DUZ=1 |
| | 152 | N X S X="Hello World" D HASH^XUSHSHP |
| | 153 | N RESULT1 S RESULT1=X |
| | 154 | N X S X="HELLO WORLD" D HASH^XUSHSHP |
| | 155 | N RESULT2 S RESULT2=X |
| | 156 | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results of different cases aren't equal") |
| | 157 | QUIT |
| | 158 | ; |
| | 159 | TENC ; @TEST - Test Encryption |
| | 160 | N VALUE S VALUE="Mary has a little lamb" |
| | 161 | S X=VALUE,X1=1,X2=234234234 |
| | 162 | D EN,DE ; encrypt, decrypt X |
| | 163 | D CHKEQ^XTMUNIT(VALUE,X,"Encryption and decryption didn't happen properly") |
| | 164 | ; |
| | 165 | N VALUE2 S VALUE2="Mary has a little lamb" |
| | 166 | S X=VALUE2,X1=88,X2=234234234 |
| | 167 | D EN ; encrypt |
| | 168 | N ENCSTR1 S ENCSTR1=X |
| | 169 | S X=VALUE2,X1=1,X2=234234234 ; Different X1 |
| | 170 | D EN ; encrypt |
| | 171 | N ENCSTR2 S ENCSTR2=X |
| | 172 | D CHKTF^XTMUNIT(ENCSTR1'=ENCSTR2,"Encrypted strings with different passwords are not supposed to be equal") |
| | 173 | QUIT |
| | 174 | ; |
| | 175 | TENC2 ; @TEST - Test Encryption by calling XUSHSHP |
| | 176 | N VALUE S VALUE="Mary has a little lamb" |
| | 177 | S X=VALUE,X1=1,X2=234234234 |
| | 178 | D EN^XUSHSHP,DE^XUSHSHP ; encrypt, decrypt X |
| | 179 | D CHKEQ^XTMUNIT(VALUE,X,"Encryption and decryption didn't happen properly") |
| | 180 | ; |
| | 181 | N VALUE2 S VALUE2="Mary has a little lamb" |
| | 182 | S X=VALUE2,X1=88,X2=234234234 |
| | 183 | D EN^XUSHSHP ; encrypt |
| | 184 | N ENCSTR1 S ENCSTR1=X |
| | 185 | S X=VALUE2,X1=1,X2=234234234 ; Different X1 |
| | 186 | D EN^XUSHSHP ; encrypt |
| | 187 | N ENCSTR2 S ENCSTR2=X |
| | 188 | D CHKTF^XTMUNIT(ENCSTR1'=ENCSTR2,"Encrypted strings with different passwords are not supposed to be equal") |
| | 189 | QUIT |
| | 190 | LENGTH ; @TEST - Test Lengths |
| | 191 | N X,X1,X2,I |
| | 192 | S (X1,X2)=982734987234 |
| | 193 | W ! |
| | 194 | F I=1:1:60 K X S $P(X,"A",I)="A" W $L(X) D EN W ?30,$L(X),! |
| | 195 | QUIT |
| | 196 | }}} |