Written by

Developer at Matirx, Israel
Question Nael Nasereldeen · Oct 27, 2019

%SYSTEM.Encryption MD5Hash function -return value conversion

Hi,

We wanted to use the MD5Hash function,

And had trouble understanding it's return value , as documented:

"Return value: 16-byte MD5 hash."

The value we wanted should have been a simple string, and we did not know how to convert the output to string.

Searching for a solution we found this article:

https://groups.google.com/forum/#!msg/intersystems-public-cache/FdkHIgS9PkQ/P7s-92kN70UJ

That had this solution that works:

"If you know what this gibberish stuff is about, it can be very simple ;)

USER> s h = ##class(%SYSTEM.Encryption).MD5Hash("f...@baz.com")
USER> s h0x = ""
USER> f i=1:1:$l(h) {s chr = $zhex($ascii($e(h,i))) s h0x = h0x _
$s($l(chr) = 1: "0"_chr, 1:chr)}
USER> w $zcvt(h0x,"l")
1d2fd35d57d574b807a807b507528b19"

And also a simpler solution:

"  s pwd="12345678"
  s md5=$system.Encryption.MD5Hash(pwd)
  s md5hex=##class(%xsd.hexBinary).LogicalToXSD(md5)
  w md5hex,! "

Is this issue addressed in Cache documentation? and is there a more standard way to get the string result?

Regards,

Nael
 

Comments

Rod Dorman · Oct 27, 2019

The value we wanted should have been a simple string, and we did not
 know how to convert the output to string
##class(%SYSTEM.Encryption).MD5Hash() does return a string, what do you mean by 'simple'? If you mean 'displayable' that will depend on what you're trying to display on.
Take a look at ##class(%SYSTEM.Encryption).Base64Encode() that will return a string with only non-control ASCII characters.

0
Nael Nasereldeen  Oct 27, 2019 to Rod Dorman

Hi,

What I mean by a simple string, is a value that you can send Via a web service for example.

Thanks.

0
Eduard Lebedyuk  Oct 28, 2019 to Nael Nasereldeen

What value are you expecting?

Base64 is often used to encode hashes:

write ##class(%SYSTEM.Encryption).Base64Encode(##class(%SYSTEM.Encryption).MD5Hash("f...@baz.com"))
0
Nael Nasereldeen  Oct 28, 2019 to Jon Willeke

I understand.

Thanks, all comments have been helpful!

Regards,

Nael

0
David Underhill  Oct 28, 2019 to Jon Willeke

That looks better than the WRC supplied code when I fist noticed the binary rather than hex values returned.

set text = "message digest"
  set md5hash = $system.Encryption.MD5Hash(text)
  set md5HashHex = ""
  for i=1:1:$Length(md5hash) {
   set md5HashHex = md5HashHex _ $Zhex($Ascii($Extract(md5hash,i)))
  }
  write md5HashHex, !


 

0
Jon Willeke  Oct 29, 2019 to David Underhill

FWIW, you can also replace the call to $extract with two-argument $ascii:

$a(md5hash,i)
0
Jon Willeke · Oct 28, 2019

Whereas the digest methods in the %SYSTEM .Encryption class return binary strings, which are documented in terms of their byte length, it is indeed conventional to display them using hexadecimal. Instead of $select, I more usually see $translate and $justify:

s h0x=h0x_$tr($j(chr,2)," ",0)

If %xsd.hexBinary is covenient, though, I'd say use that.

For a sanity check, you can compare whatever implementation you choose with the zzdump command:

USER>s digest=$system.Encryption.MD5Hash("12345678")

USER>w ##class(%xsd.hexBinary).LogicalToXSD(digest)
25D55AD283AA400AF464C76D713C07AD
USER>zzdump digest

0000: 25 D5 5A D2 83 AA 40 0A F4 64 C7 6D 71 3C 07 AD
0
Joel Espinoza · Oct 11, 2022

To encrypt to MD5 (as javascript, unix and others) I writed this classmethod, using information found here, and works very well.

ClassMethodEncripta(pass)As%String
{
setintermedio=##class(%SYSTEM.Encryption).MD5Hash(pass)
setmd5HashHex=""
fori=1:1:$Length(intermedio){
sethexaIntermedio=$Zhex($Ascii($Extract(intermedio,i)))
if$Length(hexaIntermedio)=1{
sethexaIntermedio="0"_hexaIntermedio
}
setmd5HashHex=md5HashHex_hexaIntermedio
}
return$ZConvert(md5HashHex,"L")
}

Just need to use " d Encripta("word")"

I hope could be useful!

Joe!

0