· Sep 28, 2017

Crypt-compatible COS function/implementation - has anyone seen this code?



I am looking for ObjectScript implementation of crypt-compatible function, that generates md5 salted hashes (output is in the form of $1$salt$hash). From what I understand it uses its own spin on md5 algorithm:



Does Cache have something like that built in?

Has somebody here seen it implemented somewhere?






I have found description of the underlying algorithm here:

Discussion (7)0
Log in or sign up to continue

I am trying to generate same output as crypt function (CRYPT_MD5 flavor).

So for example


returns $1$1a2b3c4d$Y5tt50CQ12xW2saeYnI43, which is not same as pure MD5 hash (like $SYSTEM.Encryption.MD5Hash).

From documentation it seems that crypt creates derived hash based on MD5, but it is not the same.

Your options are:

  • Try to compile crypt only under win x64 (libc as a whole can't be compiled under windows, but maybe you can compile crypt module)
  • PHP doc you referenced states that PHP has it's own fallback implementation when OS does not provide crypt implementation. Check where does PHP search for crypt implementation on windows - it's probably some C lib and call it too
  • Write the algorithm yourself, here's  a good guide on that
  • Use another more secure hashing algorithm, for example SHA-512

There is also CNA project - it provides an interface for using native C-compatible shared libraries without anything but Caché ObjectScript code. CNA is a wrapper for libffi. CNA consists of native library (libcna) and Caché class (CNA.CNA). It is a wrapper around $zf functions (you can use them directly too).

Here's the code to call crypt using CNA:

Class CNA.Crypt

/// do ##class(CNA.Crypt).Crypt()
ClassMethod Crypt(key = "2Ggaobjb", salt = "$1$1a2b3c4d$")
    set cna = ##class(CNA.CNA).%New("/InterSystems/forCLM/") ; Creates object of CNA.CNA class.
    do cna.LoadLibrary("/lib/x86_64-linux-gnu/")      ; Loads C standard library (crypto) in CNA

    set keyPointer = cna.ConvertStringToPointer(key) ; Converts the string into char array, and saves pointer to the first element

    set saltPointer = cna.ConvertStringToPointer(salt)

    set argTypes = $lb(cna.#POINTER, cna.#POINTER)   ; function argument types
    set result = cna.CallFunction("crypt",          ; Passes the name of the function,
                                cna.#POINTER,       ; type of return value,
                                argTypes,         ; list of argument types,
                                keyPointer, saltPointer)           ; and comma-separated arguments */    
    write cna.ConvertPointerToString(result), !      
    do cna.FreeLibrary()


Sample output:

do ##class(CNA.Crypt).Crypt()

do ##class(CNA.Crypt).Crypt("ABC", "$1$12345678$")