MiniM. Saving time.

| About | Download | Tools | Knowledge Base | How to Buy |

MiniM Overview

Getting Started




Cache Tools

GT.M Tools

Knowledge Base




MiniM Additional Tools | Sep 12, 2010

Working with the device |ZSSL|

(basic version using the OpenSSL library)

Materials used:

"Crypto" issues are not considered, there are specialized literature and websites for this.

For all examples, it is used as an OpenSSL server. The password for all certificates is "12345" (or not used at all, depends on how you generated the keys).

A simple SSL server, run as follows:

openssl.exe s_server -accept 16001 -cert server.pem -debug

Fig. 1

Launching the HTTPS Demo Server:

openssl.exe s_server -WWW -accept 16001 -cert server.pem -debug

The device supports two modes of operation: client and server, using foreign keys or using "ephemeral" keys.

How to use the device |ZSSL| in client mode.

1) 1) Create a device, specify the operation parameters.

open "|ZSSL|hostname:port"  open "|ZSSL|":(/param=value,...)

The /params parameters can be passed as follows:

/CONNECT="host:port"address:the port where we connect or transmit, together with "|ZSSL|host:port".

Do not use in conjunction with /MODE,/SOCKET

/CERT="/path/to/sertificate.pem"client certificate
/KEY="/path/to/secret/key.pem"if /KEY is not defined, then the value from /CERT is used, if it is password protected, then it is necessary to pass the /PWD option first!
/PWD="password"the password to the key (if required), preferably /PWD to pass before using the option /CERT or /KEY
/MODE=0specify that the mode of operation is "client" if, in the context of a call, the system does not know what kind of mode is obtained
/SOCKET=num_socketindicates that the connection was established by other cp-you, for example via open "|TCP|" the socket number is defined as (pseudocode):

u "|TCP|" s socketno=$v("dev",2)

/MODE,/SOCKET more priority than /CONNECT

/CAFILECA Certificate
/CAPATHThe path where to look for certificate chains

2) Make it current:

use "|ZSSL|"

3) The device is ready for exchange:

use "|ZSSL|"
write "Hello SSL!",$c(13,10)

4) Disable, close:

close "|ZSSL|"

Example 1. Normal data access (keys are generated on the fly):

USER>s dev="|ZSSL|localhost:16001"
USER>o dev
USER>u dev w "Hello SSL!",$c(13,10)
USER>c dev

The server's response (partially, "Hello..." will be on the sl. screen):

Fig. 2


Example 2. Using ready-made keys:

USER>s dev="|ZSSL|localhost:16001"
USER>o dev:(/PWD="12345":/CERT="client.pem")
USER>u dev w "Hello SSL!",$c(13,10)
USER>c dev

Please note that the "handshake" (key exchange and connection setup) can take a considerable time (this is due to the generation of "ephemeral" keys, keys for the duration of the session).

After installing the correct connection, all exchange via the "|ZSSL|" device will be carried out in transparent encryption mode, the maximum settings are selected by default, at the moment OpenSSL 1.0.0 uses the ECDHE-RSA-AES256-SHA algorithm and further in the order of enumeration:


Example 2: Reading a page from a website (with errors)
USER>s c=$c(13,10),dev="|ZSSL|" o dev
USER>u dev w "GET /asp/banking.asp HTTP/1.1",c,c r s
USER>c dev u 0 w s
s="HTTP/1.1 400 Bad Request
Content-Type: text/html
Date: Tue, 06 Jul 2010 18:54:08 GMT
Connection: close
Content-Length: 39
<h1>Bad Request (Invalid Hostname)</h1>"

How to use the device |ZSSL| in server mode.

1) Open a connection with standard MiniM method using the |TCP| device.

s dev="|TCP|"_port open dev::1 e  w "error",! Q
or use routine ^%INETD ( d.html) and connect to your chosen port, your own "daemon".
i $$ADD^%INETD("%srv","cdmn^%srvssl","%SYS",16001,"RWB",1)

2) Get the internal number of the "accepted" device.

S socket=$v("dev",1,dev)

2.1) you don't need to do a job to untie the "client" and "server" if you use %INETD.

 u dev:(/ACCEPT:/ATO=0) s socket=$v("dev",2)
 j runcmd():(:$io)
 u 0
 s %DEVICE=$i,%SOCKET=$v("dev",1)  ; (:$io)
 o "|ZSSL|":(/SOCKET=%SOCKET,...)
or when using ^%INETD, use the %SOCKET variable

3) Create a device, specify the operation parameters.

open "|ZSSL|":(/param=value,...)

Parameters can be passed as follows:

/CERT="/path/to/certificate.pem"server certificate, required!
/KEY="/path/to/secret/key.pem"if /KEY is not defined, then the value from /CERT is used, if it is password protected, then it is necessary to pass the /PWD option first!
/PWD="password"the password to the certificate (if required), preferably /PWD to pass before using the option /CERT or /KEY
/MODE=1specify that the operating mode is "server"
/SOCKET=num_socketIndicates the number of the "accepted" device socket
/CAFILECA Certificate
/CAPATHThe path where to look for certificate chains

Please note that the presence of the /CERT or /KEY parameter is strictly mandatory, since it is not provided for ephemeral key generation servers at the time of session creation, including it is necessary to pass /PWD before /CERT/KEY. When the client accesses the server, the client must have a valid server certificate, otherwise there may be problems with the handshake (denial of service).

4) Next, I / O is carried out as in client mode, the main thing is that if you need to get a new client connection, then perform paragraphs 2-3, i.e. |ZSSL| performs only the role of a "crypto" channel.

5) Close the device in reverse order, first |ZSSL| then |TCP|.

See example %zssld.r

Using the library as a ZDLL module (see the description of the $zdll function)

The library supports the $dll interface, the following functions are implemented:


Returns the openssl version and the library version zssl.dll


Saves 1024 bytes of pseudo-random data in a file, by default ssl.rnd.
The file is necessary for the correct operation of the "pseudo-randomness" generation mechanism. Do not transfer this file to anyone, delete it periodically if possible. Returns how many bytes were actually written to the file (usually 1024 bytes).


Loads a pseudo-random data file to "improve" statistics when generating a pseudo-random data stream/keys, etc., the default file name is zssl.rnd. Returns how many bytes were actually read from the specified file.

Fig. 4


Returns a cryptographically stable sequence of pseudorandom bytes, since system processes are used when generating the context, then generating a large number of data can take a considerable time. It is recommended to use together with RAND_pseudo_bytes, for example, to use up to 8-16 bytes of RAND_bytes, and then RAND_pseudo_bytes. If the countbytes parameter is not specified, the MINIM_STR_MAX size is returned, be careful, the process may hang!


Fast generation of pseudo-random bytes. Returns a string of bytes, with a length of countbytes, if the parameter is not specified, then a MINIM_STR_MAX byte is generated. It is recommended to use this function to generate a pseudo-random byte stream.

Fig. 5


Returns a signature/hash on the specified string,the returned block length depends on the algorithm used. Example:

s dg=$zdll("call","zssl.dll","EVP_Digest","MD5","Hello MINIM!")
Returns 16 bytes. Depending on the implementation, the library supports the most diverse algorithms: md4, md5, mdc2, rmd160, sha, sha1, sha512, etc. GOST algorithms are not supported in this version.

Fig. 6


If there is a need to generate a hash for a block larger than MINIM_STR_MAX , then you can use these functions. EVP_DigestInit initializes the context of the specified algorithm, and EVP_DigestUpdate adds data to the context, EVP_DigestFinal - finally finalizes the hash, returns its value and releases the context. Usage example:

S ctx=$zdll("call","zssl.dll","EVP_DigestInit","MD5"),i=""
F  S i=$o(str(i)) Q:i=""   I  \\ the line continues 
S dg=$zdll("call","zssl.dll","EVP_DigestFinal",ctx)

Do not lose the context, a variable of type ctx in the example, otherwise there will be a memory leak (when the process is completed by hang, the memory leak is neutralized, i.e. relevant only for the tech. process).


Returns the hash HMAC (hash message authentication code), the functionality is completely similar to the EVP_Digest function. Key-the key to "intimidate" the hash. ;-)

. 7


HMAC_Init initializes a HMAC_CTX structure to use the hash function evp_md and the key key which is key_len bytes long.
HMAC_Update can be called repeatedly with chunks of the message to be authenticated (len bytes at data).
HMAC_Final places the message authentication code in md, which must have space for the hash function output.
The functionality completely coincides with EVP_Digest*. Example:

S ctx=$zdll("call","zssl.dll","HMAC_Init","RIPEMD160","key"),i=""
F  S i=$o(str(i)) Q:i=""     \\ line continues
   I $zdll("call","zssl.dll","HMAC_Update",ctx,str(i))
S dg=$zdll("call","zssl.dll","HMAC_Final",ctx)


Setting specific options, different values are set for each HMAC algorithm, check the documentation for the OpenSSL library for the HMAC_CTX_set_flags function. Call after HMAC_Init but before the first use of HMAC_Update or HMAC_Final.


Performs string encryption with the specified algorithm, the returned value may be longer than the original one, due to the alignment of the final values for some block algorithms. Key is the key, iv is an additional initialization vector. Example:

S strcry=$zdll("call","zssl.dll","EVP_Encrypt","RC4","key","","Hello!")

Available symmetric de/encryption algorithms (rsa/dsa algorithms are not implemented in this version zssl.dll):

aes-128-cbc       aes-128-ecb       aes-192-cbc       aes-192-ecb
aes-256-cbc       aes-256-ecb       base64            bf
bf-cbc            bf-cfb            bf-ecb            bf-ofb
camellia-128-cbc  camellia-128-ecb  camellia-192-cbc  camellia-192-ecb
camellia-256-cbc  camellia-256-ecb  cast              cast-cbc
cast5-cbc         cast5-cfb         cast5-ecb         cast5-ofb
des               des-cbc           des-cfb           des-ecb
des-ede           des-ede-cbc       des-ede-cfb       des-ede-ofb
des-ede3          des-ede3-cbc      des-ede3-cfb      des-ede3-ofb
des-ofb           des3              desx              idea
idea-cbc          idea-cfb          idea-ecb          idea-ofb
rc2               rc2-40-cbc        rc2-64-cbc        rc2-cbc
rc2-cfb           rc2-ecb           rc2-ofb           rc4
rc4-40            seed              seed-cbc          seed-cfb
seed-ecb          seed-ofb


Used if it is necessary to encrypt a block larger than MINIM_STR_MAX.
First, the context of the algorithm is initialized, then all strings are encrypted in the loop, the last finalization also turns the remains of the encrypted string or an empty one.


Returns the decrypted string, the inverse function EVP_Encryptfinal.


EVP_Decrypt* works similarly. Reverse EVP_Encrypt*
In case of problems, all functions generate a Z-error. If you already have a non-zero context, then do not forget to release it, i.e., regardless of whether there is an error, finalize (functions of the *Finale* type).

See the examples in zssltest.rsa

Installing the library

1. Copy the file zssl.dll to the directory where MINIM is installed. For example:

copy zssl.zdll c:\minim\bin\

2. If you have the ssl.c source code in the delivery and you have modified it, then I recommend building it with the VC++ ver 7 and higher compiler, or Borland 5.0 C++ (free version). For example, attached .bat files for assembly by both compilers.


1. Attached as an example .bat files for running OpenSSL in client and server mode.

2. The server.* and client keys.* I recommend generating it yourself, at the same time study the OpenSSL command line.

3. It is also advisable to familiarize yourself with the above links, additionally in the doc-add catalog, there are various materials and examples of working with SSL.

Download (ZIP, 2.2Mb)

This text was translated to English 2022/12/15.

(L) Onix, 2022/12/15

Copyright (C) Eugene Karataev
Info Support