114 | | ; |
115 | | RUNTESTS S IO=$P S DIQUIET=1 D DT^DICRW D:$L($T(EN^XTMUNIT)) EN^XTMUNIT($T(+0),1) QUIT |
116 | | THASH ; @TEST - Test Hashing |
117 | | N DUZ |
118 | | S DUZ=1 N X S X="HELLO WORLD" D HASH |
119 | | N RESULT1 S RESULT1=X |
120 | | S DUZ=1 N X S X="HELLO WORLD" D HASH |
121 | | N RESULT2 S RESULT2=X |
122 | | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results are not equal") |
123 | | ; |
124 | | S DUZ=1 N X S X="HELLO WORLD" D HASH |
125 | | N RESULT1 S RESULT1=X |
126 | | S DUZ=2 N X S X="HELLO WORLD" D HASH |
127 | | N RESULT2 S RESULT2=X |
128 | | D CHKTF^XTMUNIT(RESULT1'=RESULT2,"Hash results are not supposed to be equal") |
129 | | ; |
130 | | S DUZ=1 |
131 | | N X S X="Hello World" D HASH |
132 | | N RESULT1 S RESULT1=X |
133 | | N X S X="HELLO WORLD" D HASH |
134 | | N RESULT2 S RESULT2=X |
135 | | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results of different cases aren't equal") |
136 | | QUIT |
137 | | ; |
138 | | THASH2 ; @TEST - Test Hashing using main calling routine XUSHSHP |
139 | | N DUZ |
140 | | S DUZ=1 N X S X="HELLO WORLD" D HASH^XUSHSHP |
141 | | N RESULT1 S RESULT1=X |
142 | | S DUZ=1 N X S X="HELLO WORLD" D HASH^XUSHSHP |
143 | | N RESULT2 S RESULT2=X |
144 | | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results are not equal") |
145 | | ; |
146 | | S DUZ=1 N X S X="HELLO WORLD" D HASH^XUSHSHP |
147 | | N RESULT1 S RESULT1=X |
148 | | S DUZ=2 N X S X="HELLO WORLD" D HASH^XUSHSHP |
149 | | N RESULT2 S RESULT2=X |
150 | | D CHKTF^XTMUNIT(RESULT1'=RESULT2,"Hash results are not supposed to be equal") |
151 | | ; |
152 | | S DUZ=1 |
153 | | N X S X="Hello World" D HASH^XUSHSHP |
154 | | N RESULT1 S RESULT1=X |
155 | | N X S X="HELLO WORLD" D HASH^XUSHSHP |
156 | | N RESULT2 S RESULT2=X |
157 | | D CHKEQ^XTMUNIT(RESULT1,RESULT2,"Hash results of different cases aren't equal") |
158 | | QUIT |
159 | | ; |
160 | | TENC ; @TEST - Test Encryption |
161 | | N VALUE S VALUE="Mary has a little lamb" |
162 | | S X=VALUE,X1=1,X2=234234234 |
163 | | D EN,DE ; encrypt, decrypt X |
164 | | D CHKEQ^XTMUNIT(VALUE,X,"Encryption and decryption didn't happen properly") |
165 | | ; |
166 | | N VALUE2 S VALUE2="Mary has a little lamb" |
167 | | S X=VALUE2,X1=88,X2=234234234 |
168 | | D EN ; encrypt |
169 | | N ENCSTR1 S ENCSTR1=X |
170 | | S X=VALUE2,X1=1,X2=234234234 ; Different X1 |
171 | | D EN ; encrypt |
172 | | N ENCSTR2 S ENCSTR2=X |
173 | | D CHKTF^XTMUNIT(ENCSTR1'=ENCSTR2,"Encrypted strings with different passwords are not supposed to be equal") |
174 | | QUIT |
175 | | ; |
176 | | TENC2 ; @TEST - Test Encryption by calling XUSHSHP |
177 | | N VALUE S VALUE="Mary has a little lamb" |
178 | | S X=VALUE,X1=1,X2=234234234 |
179 | | D EN^XUSHSHP,DE^XUSHSHP ; encrypt, decrypt X |
180 | | D CHKEQ^XTMUNIT(VALUE,X,"Encryption and decryption didn't happen properly") |
181 | | ; |
182 | | N VALUE2 S VALUE2="Mary has a little lamb" |
183 | | S X=VALUE2,X1=88,X2=234234234 |
184 | | D EN^XUSHSHP ; encrypt |
185 | | N ENCSTR1 S ENCSTR1=X |
186 | | S X=VALUE2,X1=1,X2=234234234 ; Different X1 |
187 | | D EN^XUSHSHP ; encrypt |
188 | | N ENCSTR2 S ENCSTR2=X |
189 | | D CHKTF^XTMUNIT(ENCSTR1'=ENCSTR2,"Encrypted strings with different passwords are not supposed to be equal") |
190 | | QUIT |
191 | | LENGTH ; @TEST - Test Lengths |
192 | | N X,X1,X2,I |
193 | | S (X1,X2)=982734987234 |
194 | | W ! |
195 | | F I=1:1:60 K X S $P(X,"A",I)="A" W $L(X) D EN W ?30,$L(X),! |
196 | | QUIT |
| 281 | Please note that while the above conversion can be made rerun-safe, this is not taken into consideration here. This code can only be run once without it proving to be harmful. However, if it is ran again, the reverse operation can be performed to correct the action of the second run. |
| 282 | |
| 283 | I didn't write example code for Radiology/Nuclear Medicine as I don't have test data in that package. |
| 284 | |
| 285 | == Impact on the rest of VISTA == |
| 286 | Analysis of the impact will take two phases: That of the Hash and that of the change in encryption. |
| 287 | |
| 288 | === Impact of the new hashing algorithm === |
| 289 | Replacement of the Hash algorithm presents no foreseable problems. The maximum length of the output of the new hash is identical to the maximum length of the old. You only need to ensure that at the time of installing the new hash you convert the old unencrypted electronic signatures into the hashed form so that the user's electronic signatures will continue working. |
| 290 | |
| 291 | === Impact of the new encryption algorithm === |
| 292 | This area is far more problematic for two reasons: the output of the hash is random data (which Fileman cannot store), and with block ciphers input is padded to achieve block size. Both of these issues mean that to achieve proper encryption, you will need to base64 encode output from a block cipher so the result can be stored in Fileman. In the end, it means that the encrypted data is much longer than the original data (but not quite double the size). This means that we need to expand the Fileman fields where the encrypted data is stored. The KIDS file accompanying this article expands the 4 TIU fields that store encrypted data to 120 characters each from 60 characters. It's anticipated that other fields (especially field 10 in File 74) will need to be expanded depending on the number of packages you are using. The alternative is to change the encryption algorithm to something much weaker (even rot5) to be able to retain the current sizes. |
| 293 | |
| 294 | The following is an analysis of all the impacted area in VISTA: |
| 295 | {{{ |
| 296 | r/DVBCHLUT.m: D EN^XUSHSHP |
| 297 | HINQ package. Unused. |
| 298 | |
| 299 | r/EEOEEXMT.m:LONG K EEOPT S EENOD=DECR,EEOL=$L(EENOD),EEOC="" F EEOC=0:50:250 S X=$E(EENOD,EEOC+1,EEOC+50) Q:X="" D EN^XUSHSHP D |
| 300 | r/EEOEEXMT.m: D EN^XUSHSHP S ^TMP($J,FEE)=X |
| 301 | r/EEOEEXMT.m: I $L(DECR)<50 S X=DECR,X2=FEE+1 D EN^XUSHSHP S ^TMP($J,FEE+1)=X,FEE=FEE+2 Q |
| 302 | r/EEOEXMT2.m: K EEOPT S EENOD=DECR,EEOL=$L(EENOD),EEOC="" F EEOC=0:50:250 S X=$E(EENOD,EEOC+1,EEOC+50) Q:X="" D EN^XUSHSHP D |
| 303 | r/EEOEXMT2.m: D EN^XUSHSHP S ^TMP($J,FEE)=X |
| 304 | r/EEOEXMT2.m: I $L(DECR)<50 S X=DECR,X2=FEE+1 D EN^XUSHSHP S ^TMP($J,FEE+1)=X,FEE=FEE+2 Q |
| 305 | EEO COMPLAINT TRACKING. Unused. |
| 306 | |
| 307 | r/ENTIUTL1.m: . S X=ENSTR,X1=ENDA,X2=1 D EN^XUSHSHP S ENSTRH=X ; hashed string |
| 308 | ENGINEERING. Unused. |
| 309 | |
| 310 | r/MCESPRT.m: D EN^XUSHSHP |
| 311 | MEDICINE. Probably unused. Used only by $$ENCODE^MCESPRT which is only called from SIGN^MCESEDT2 on the CLI. |
| 312 | |
| 313 | r/OOPSESIG.m: W " ... signed." S X=ESNAM,X1=DUZ,X2=IEN D EN^XUSHSHP S ESIG=DUZ_"^"_X |
| 314 | r/OOPSGUIS.m: D EN^XUSHSHP |
| 315 | r/OOPSVAL1.m: D EN^XUSHSHP |
| 316 | Automated Safety Incident Surveillance Tracking System. Unused. |
| 317 | |
| 318 | r/PRCASIG.m: D EN^XUSHSHP |
| 319 | r/PRCUESIG.m:ENCODE(X,X1,X2) D EN^XUSHSHP Q X |
| 320 | IFCAP. Not sure if it's used. |
| 321 | |
| 322 | r/PRPFSIG.m:ENCODE(X,X1,X2) D EN^XUSHSHP Q X |
| 323 | Patient Funds. Direct Global Set. No risk. |
| 324 | |
| 325 | r/PRSAOTX.m: S X=ESNAM,X1=DUZ,X2=DA D EN^XUSHSHP |
| 326 | Global Set. No risk. |
| 327 | r/PRSASC1.m: S DFN=$P(AP(1,DA),"^",1),ACT=$P(AP(1,DA),"^",2),COM=$P(AP(1,DA),"^",3),X=ESNAM,X1=DUZ,X2=DA D EN^XUSHSHP |
| 328 | r/PRSASC1.m: S DFN=$P(AP(2,DA),"^",1),ACT=$P(AP(2,DA),"^",2),COM=$P(AP(2,DA),"^",3),X=ESNAM,X1=DUZ,X2=DA D EN^XUSHSHP |
| 329 | r/PRSASC1.m: S DFN=$P(AP(3,DA),"^",1),ACT=$P(AP(3,DA),"^",2),COM=$P(AP(3,DA),"^",3),X=ESNAM,X1=DUZ,X2=DA D EN^XUSHSHP |
| 330 | r/PRSASC1.m: S X=ESNAM,X1=DUZ,X2=DFN D EN^XUSHSHP |
| 331 | All global sets. No risk. |
| 332 | PAID. |
| 333 | |
| 334 | r/RACTVR4.m:X11 S X1=RASIG("PER"),X=RASIG("NAME"),X2=DA D EN^XUSHSHP S RASIGCDE=X |
| 335 | r/RACTVR.m:X34 S X1=RASIG("PER"),X=RASIG("NAME"),X2=DA D EN^XUSHSHP S RASIGCDE=X |
| 336 | r/RACTWR2.m:X5 S X1=RASIG("PER"),X=RASIG("NAME"),X2=DA D EN^XUSHSHP S RASIGCDE=X |
| 337 | r/RACTWR4.m:X5 S X1=RASIG("PER"),X=RASIG("NAME"),X2=DA D EN^XUSHSHP S RASIGCDE=X |
| 338 | r/RAHLO1.m:LOCK1 I $D(RAESIG) S X=RAESIG,X1=$G(RAVERF),X2=RARPT D EN^XUSHSHP S RAESIG=X |
| 339 | 74,10 ELECTRONIC SIGNATURE CODE 0;10 FREE TEXT |
| 340 | |
| 341 | INPUT TRANSFORM: K:$L(X)>50!($L(X)<1) X |
| 342 | OUTPUT TRANSFORM: S Y=" <Hidden>" |
| 343 | ***THIS NEEDS TO CHANGE LENGTH TO 80 CHARACTERS AND RECORDS CONVERTED!*** |
| 344 | Radiology |
| 345 | |
| 346 | r/RMPOBILU.m: D EN^XUSHSHP |
| 347 | r/RMPR4LI.m: D EN^XUSHSHP Q X |
| 348 | r/RMPRSEC.m: D EN^XUSHSHP Q X |
| 349 | Home Oxygen Billing. Unused. |
| 350 | |
| 351 | r/SPNLGUCD.m: D EN^XUSHSHP |
| 352 | Spinal code dysfunction. Unused. |
| 353 | |
| 354 | r/TIULC1.m: D EN^XUSHSHP |
| 355 | TIU Already accounted for. |
| 356 | |
| 357 | r/VAQHSH1.m: I ('DCRYPT) D EN^XUSHSHP Q X |
| 358 | PATIENT DATA EXHANGE. Unused. |
| 359 | |
| 360 | r/XUSESIG1.m: S X=ESBLK,X1=+CHKSUM,X2=1 D EN^XUSHSHP |
| 361 | API. Not referenced anywhere. |
| 362 | |
| 363 | r/XUSTZ.m: S X1=IOS,X2=DT F I=1:1:XUF(.2) S X=XUF(I) D EN^XUSHSHP S XUF(I)=X |
| 364 | Only used as hashing it seems. Global set. Throw away data. No action needed. |
| 365 | |
| 366 | No matches in the DD global. |
| 367 | }}} |