Cryptographic protocol experiment -- sigma protocol

Posted by just1ncase on Tue, 04 Jan 2022 10:58:38 +0100

Cryptographic protocol experiment -- sigma protocol

Experiment 1 implementation of DH authentication key exchange protocol

SIGMA protocol

principle

step

1. Configure miracl and openssl library environment

Configuring the miracl library environment

  1. The configuration is a little troublesome. First, download the source code and paste a miracl source code address

Link: https://pan.baidu.com/s/17DXQYBwdNLyiIYq-GVjFdw
Extraction code: nht3

  1. Then compile the source code to generate a static link library, which is a little troublesome. You can directly use others to generate a good static link library.

Link: https://pan.baidu.com/s/1mVyfiZ-6LeUjW9S-WXf_8A
Extraction code: bvlz

Then the four files miracl lib,miracl.pdb,miracl.h and mirdef H copy to the project folder and import the project (right click Project - > Add - > existing item)

  1. Next, configure the environment: (right click Project - > Add - > properties)
  • VC + + Directory - > including directory and Library Directory

In the include directory, select the include folder address in the miracl source code, and in the library directory, select the lib folder address in the miracl source code

  • Linker - > General - > additional Library Directory: add project address

  • Linker - > Input - > Add dependency: enter miracl lib

  • C/C + + Directory - > attachment include directory: select the include folder address in the miracl source code from the include directory

Note: the C/C + + option must be in the source file c/.cpp file

Note: because the miracl library is written by C, if you want to call it in the c++ file, you need to add the following code

extern "C"
{
	#include "miracl.h"
	#include "mirdef.h"
}

4. Project regeneration

Configure openssl library environment

Reference link:< (15 messages) OpenSSL environment configuration example in vs_ huang714 column - CSDN blog_ vs configuring OpenSSL>

  1. You can choose to compile the source code similar to the miracl library. It is recommended to download the compiled class library directly and paste an address

    Link: https://pan.baidu.com/s/1Xw_mYFSDW59JGnkCvGUr2g
    Extraction code: hsga

  2. Configuration environment

  • VC + + Directory - > including directory and Library Directory

  • Linker - > Input - > Add dependency: enter ssleay lib,libeay.lib

  1. Put libeay32.0 in the openssl folder DLL and ssleay32 DLL file is in the folder where the project is located

  1. Project rebuild
2. Use miral library to realize the following functions
  • Generating large prime numbers
big g = mirvar(0);   //Generators of cyclic groups
big p = mirvar(0);   //Large prime
big q1 = mirvar(0);  //Using q1 to generate p

bigdig(150, 10, q1);//Generate a 150 bit random number, about 512 bits, about 200 bits, about 660 bits, about 300 bits and about 1000 bits
nxsafeprime(0, 0, q1, p);//Generate a safe prime P greater than q
printf("The generated large prime number is:\n");
printf("p = ");
cotnum(p, stdout);
  • Calculate the public key used in Alice and Bob key exchange protocol
big x1 = mirvar(0);  //Alice's private key
big x2 = mirvar(0);  //Bob's private key
big X1 = mirvar(0);  //Alice's public key
big X2 = mirvar(0);  //Bob's public key

copy(get_generator(p), g);
printf("Cyclic group Gp A generator of is: \n");
printf("g=");
cotnum(g, stdout);

//Calculate respective public keys
convert(134, x1); 
convert(2374, x2);
powmod(g, x1, p, X1);  //Calculate Alice public key
powmod(g, x2, p, X2);  //Calculate Bob public key
cout << "Alice,Bob Public key( g^x)Respectively" << endl;
cotnum(X1, stdout);
cotnum(X2, stdout);
  • Finding generators of cyclic groups

    Finding generators is a difficult problem. It is difficult to find all generators of a cyclic group. One of them can be found by traversal.

    Judgment method of original root:
    g 2 m o d p ! = 1 a n d g q m o d p ! = 1 a n d g p − 1 m o d p = 1 p = 2 q ; g^2 mod p!=1 \quad and\quad g^q mod p !=1 \quad and \quad g^{p-1} mod p=1\\ p=2q; g2modp!=1andgqmodp!=1andgp−1modp=1p=2q;
    Generate the original source program: generatorg cpp

    extern "C"
    {
    #include "miracl.h"
    #include "mirdef.h"
    }
    
    #include<stdio.h>
    #include<math.h>
    #include <stdlib.h>
    #include <conio.h>
    #include "miracl.h"
    #include "generatorg.h"
    
    big get_generator(big p)  //Get a primitive root of p
    {
    	big one = mirvar(1);
    	big two = mirvar(2);
    	big g = mirvar(0); //Primordial root
    	big r1 = mirvar(0);
    	big r2 = mirvar(0);
    	big q = mirvar(0);
    	big temp_up = mirvar(0);
    	decr(p, 1, temp_up); //temp_up=p-1
    	fdiv(temp_up, two, q); //q=
    	while (TRUE) {
    		bigrand(temp_up, g); // Randomly generate a number less than p-1
    		powmod(g, two, p, r1);
    		powmod(g, q, p, r2);
    		if (mr_compare(r1, one) && mr_compare(r2, one)) {  //mr_ Compare (big x, big Y): when x = y, it returns 0, that is, G ^ 2 = 1 mod p & & G ^ (p-1 / 2) = 1 mod P
    			return g;
    		}
    	}
    }
    

    Header file: generator h

    #pragma once
    #include<stdio.h>
    #include<math.h>
    #include "miracl.h"
    #include <stdlib.h>
    #include <conio.h>
    
    big get_generator(big p);
    

Attachment: miracl common library functions

Reference link https://blog.csdn.net/shuilan0066/article/details/8520337

See manual in miracl library for details Doc document

Function prototypeFunction function
miracl *mirsys(int nd, int nb)Initialize the MIRACL system. nd is the number of digits and nb is the base
void mirkill(big x)Free the memory occupied by a large number of memory
void mirexit()Clear the MIRACL system and release all internal variables
void absol(big x,big y)Find absolute value
void add(big x,big y,big z)Find the addition of large numbers z=x+y
void bigbits(int n,big x)Randomly generate an n-bit large number
void bigdig(int n, int b, big x)Generate a random number with specified length, n is the length and b is the base
void bigrand(big w, big x)Generate a large random number less than w
int cinstr(big x, char*s)Converts a large number string to a large number
int cotstr(big x, char *s)A large number is converted into a string according to its hexadecimal, and the length of the string is returned
int mr_compare(big x,big y)Compare the size of two numbers: return + 1 when x > y, return 0 when x = y, and return - 1 when x < y
void convert(int n, big x)Converts an integer n to a large number x
void copy(big x, big y)Assign a large number to another large number
void incr(big x, int n, big z)A large number plus an integer z=x+n
void decr(big x, int n, big z)Subtract an integer from a large number, z=x-n
void divide(big x, big y, big z)Divide two large numbers, z=x/y; x=x mod y
void multiply(big x, big y, big z)Multiply two large numbers, z=x.y
void fft_mult(big x, big y, big z)Use Fast Fourier algorithm to calculate the product of two large numbers, z=x.y
BOOL subdivisible(big x, int n)Test whether n can divide x
BOOL divisible(big x, big y)Test whether the large number x can divide the large number y
void premult(big x, int n, big z)Multiply a large number by an integer, z=n.x
int subdiv(big x, int n, big z)A large number divided by an integer, z=x/n, returns the remainder
intigcd(int x, int y)Returns the maximum common divisor of two integers
int egcd(bigx, big y, big z)Calculate the maximum common divisor of two large numbers, z=gcd(x,y)
int xgcd(bigx, big y, big xd, big yd, big z)The extended maximum common divisor of two large numbers can also be used to calculate the modular inverse
void negify(big x, big y)Negative sign for large number
int numdig(big x)Returns the number of digits in the large number x
void expb2(int n, big x)Calculate the large number of the n-th power of 2
void expint(intb, int n, big x)Calculate the large number of the n-th power of b
unsigned int invers(unsigned int x, unsigned int y)Calculates the modular inverse of two unsigned integers (requiring mutual prime), and returns x-1 mod y
BOOL isprime(bigx)Judge whether a large number is prime
void powmod(big x, big y,big z, big w)Modular exponentiation, w = x y m o d z w=x^y mod z w=xymodz
void sftbit(big x, int n,big z)Shift a large number to the left or right by N bits. When n is a positive number, it shifts to the left and when n is a negative number, it shifts to the right
3. Use openssl library to realize the following functions

Reference link:< C/C + + uses openssl for digest, encryption and decryption (md5, sha256, des, rsa) - findumars - blog Garden (cnblogs.com)>

  • Summarize identity information (take md5 as an example)

In the SIGMA protocol, we need to abstract the identity information (name, ID number, etc.) of Alice and Bob.

Generate summary function source program: MAC cpp

//Using openssl to generate md5 summary

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>    
#include <cassert>  
#include <string>    
#include <vector>    
#include "openssl/md5.h"       
#include "openssl/pem.h" 
#include "mac.h"

using namespace std;

void md5(string& srcStr, string& encodedStr, string& encodedHexStr)  //Incoming plaintext, summary character, summary character, summary string
{
    // Call md5 hash    
    unsigned char mdStr[33] = { 0 };
    MD5((const unsigned char*)srcStr.c_str(), srcStr.length(), mdStr);//c_ The str() function returns a pointer constant pointing to the normal C string. The content is the same as this string. In order to be compatible with C

    // Hash string    
    encodedStr = string((const char*)mdStr);
    // Hex string after hash 32 bytes    
    char buf[65] = { 0 };
    char tmp[3] = { 0 };
    for (int i = 0; i < 32; i++)
    {
        sprintf(tmp, "%02x", mdStr[i]);  //sprintf() format output function (graph)
        //x means output in hexadecimal form, 02 means less than two bits, and 0 is added in front of it. If it exceeds two bits, it will be output in actual form
        strcat(buf, tmp);
    }
    buf[32] = '\0'; // Followed by 0, truncated from 32 bytes    
    encodedHexStr = string(buf);
}

Generate summary function header file: MAC h

#pragma once
#include <iostream>    
#include <cassert>  
#include <string>    
#include <vector>    
#include "openssl/md5.h"       
#include "openssl/pem.h" 

using namespace std;

void md5(string& srcStr, string& encodedStr, string& encodedHexStr);
  • Pair public key ( g x , g y ) (g^x,g^y) (gx,gy) sign and verify

    Public key signature source program: sign cpp

#include<openssl/pem.h>
#include<openssl/ssl.h>
#include<openssl/rsa.h>
#include<openssl/evp.h>
#include<openssl/bio.h>
#include<openssl/err.h>
#include <stdio.h>
#include<iostream>
#include<fstream>
#include "sign.h"

using namespace std;

//Write the string public PEM file
int createPublicFile(const char* file, const string& pubstr)
{
    if (pubstr.empty())
    {
        printf("public key read error\n");
        return (-1);
    }
    int len = pubstr.length();
    string tmp = pubstr;
    for (int i = 64; i < len; i += 64)
    {
        if (tmp[i] != '\n')
        {
            tmp.insert(i, "\n");
        }
        i++;
    }
    tmp.insert(0, "-----BEGIN PUBLIC KEY-----\n");
    tmp.append("\n-----END PUBLIC KEY-----\n");

    //Write file
    ofstream fout(file);
    fout << tmp;

    return (0);
}

//Write the string private PEM file
int createPrivateFile(char* file, const string& pristr)
{
    if (pristr.empty())
    {
        printf("public key read error\n");
        return (-1);
    }
    int len = pristr.length();
    string tmp = pristr;
    for (int i = 64; i < len; i += 64)
    {
        if (tmp[i] != '\n')
        {
            tmp.insert(i, "\n");
        }
        i++;
    }
    tmp.insert(0, "-----BEGIN RSA PRIVATE KEY-----\n");
    tmp.append("-----END RSA PRIVATE KEY-----\n");

    //Write file
    ofstream fout(file);
    fout << tmp;

    return (0);
}

//Read key
RSA* createRSA(unsigned char* key, int publi)
{
    RSA* rsa = NULL;
    BIO* keybio;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio == NULL)
    {
        printf("Failed to create key BIO\n");
        return 0;
    }
    if (publi)
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
    else
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
    if (rsa == NULL)
        printf("Failed to create RSA\n");

    return rsa;
}

//Private key signature
int private_sign(const unsigned char* in_str, unsigned int in_str_len, unsigned char* outret, unsigned int* outlen, unsigned char* key)
{
    RSA* rsa = createRSA(key, 0);
    int result = RSA_sign(NID_sha1, in_str, in_str_len, outret, outlen, rsa);
    if (result != 1)
    {
        printf("sign error\n");
        return -1;
    }
    return result;
}

//Public key signature verification
int public_verify(const unsigned char* in_str, unsigned int in_len, unsigned char* outret, unsigned int outlen, unsigned char* key)
{
    RSA* rsa = createRSA(key, 1);
    int result = RSA_verify(NID_sha1, in_str, in_len, outret, outlen, rsa);
    if (result != 1)
    {
        printf("verify error\n");
        return -1;
    }

    return result;
}

Public key signature header file: sign h

#pragma once

#include<openssl/pem.h>
#include<openssl/ssl.h>
#include<openssl/rsa.h>
#include<openssl/evp.h>
#include<openssl/bio.h>
#include<openssl/err.h>
#include <stdio.h>
#include<iostream>
#include<fstream>

using namespace std;

int createPublicFile(const char* file, const string& pubstr);
int createPrivateFile(char* file, const string& pristr);
RSA* createRSA(unsigned char* key, int publi);
int private_sign(const unsigned char* in_str, unsigned int in_str_len, unsigned char* outret, unsigned int* outlen, unsigned char* key);
int public_verify(const unsigned char* in_str, unsigned int in_len, unsigned char* outret, unsigned int outlen, unsigned char* key);

Main program: main cpp

#define _CRT_SECURE_NO_WARNINGS
extern "C"
{
	#include "miracl.h"
	#include "mirdef.h"
}

#include <iostream>
#include <cstdio>
#include <string.h>
#include "miracl.h"
#include "mirdef.h"
#include "generatorg.h"
#include "mac.h"
#include "sign.h"

using namespace std;


//ALice public key
char publicKey1[] = "-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";

//Alice private key
char privateKey1[] = "-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy\n"\
"vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9\n"\
"Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9\n"\
"yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l\n"\
"WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q\n"\
"gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8\n"\
"omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e\n"\
"N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG\n"\
"X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd\n"\
"gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl\n"\
"vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF\n"\
"1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu\n"\
"m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ\n"\
"uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D\n"\
"JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D\n"\
"4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV\n"\
"WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5\n"\
"nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG\n"\
"PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA\n"\
"SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1\n"\
"I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96\n"\
"ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF\n"\
"yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5\n"\
"w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX\n"\
"uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw\n"\
"-----END RSA PRIVATE KEY-----\n";


int main()
{ 
	miracl* mips = mirsys(2400, 10);

	big g = mirvar(0);   //Generators of cyclic groups
	big p = mirvar(0);   //Large prime
	big q1 = mirvar(0);  //Using q1 to generate p
	big x1 = mirvar(0);  //Alice's private key
	big x2 = mirvar(0);  //Bob's private key
	big X1 = mirvar(0);  //Alice's public key
	big X2 = mirvar(0);  //Bob's public key

	bigdig(100, 10, q1);//Generate a 150 bit random number, about 512 bits, about 200 bits, about 660 bits, about 300 bits and about 1000 bits
	nxsafeprime(0, 0, q1, p);//Generate a safe prime P greater than q
	printf("The generated large prime number is:\n");
	printf("p = ");
	cotnum(p, stdout);

	copy(get_generator(p), g);
	printf("Cyclic group Gp A generator of is: \n");
	printf("g=");
	cotnum(g, stdout);

	//Calculate respective public keys
	convert(134, x1); 
	convert(2374, x2);
	powmod(g, x1, p, X1);  //Calculate Alice public key
	powmod(g, x2, p, X2);  //Calculate Bob public key
	cout << "Alice,Bob Public key( g^x)Respectively" << endl;
	cotnum(X1, stdout);
	cotnum(X2, stdout);

	//Encrypt the identity information of Alice and Bob (take the name as an example)
	string srcText1 = "Alice";
	string srcText2 = "Bob";
	string encryptText1;
	string encryptHexText1;
	string encryptText2;
	string encryptHexText2;

	cout << "===Alice,Bob Their identity information is ===" << endl;
	cout << srcText1 <<" "<<srcText2<<endl;
  
	cout << "===yes Alice,Bob Identity information for md5 The summary result is ===" << endl;
	md5(srcText1, encryptText1, encryptHexText1);
	md5(srcText2, encryptText2, encryptHexText2);
	cout << "Alice Identity summary characters: " << encryptText1<< endl;
	cout << "Alice Identity summary string(16 Hexadecimal 32 bytes):  " << encryptHexText1 << endl;
	cout << "Bob Identity summary characters: " << encryptText2 << endl;
	cout << "Bob Identity summary string(16 Hexadecimal 32 bytes):  " << encryptHexText2<< endl;

	//autograph
	char gx[2048],gy[1024];
	cotstr(X1, gx);
	cotstr(X2, gy);
	strcat(gx, gy);
	printf("%s\n", gx);
	
	cout << strlen(gx) << endl;

	unsigned char signret[4098] = {};
	unsigned int siglen;

	cout << "===Private key signature public key authentication===" << endl;
	int ret = private_sign((const unsigned char*)gx, strlen(gx), signret, &siglen, (unsigned char*)privateKey1);
	if (ret)	cout << "Signature succeeded" << endl;
	else cout << "Signature failed" << endl;
	ret = public_verify((const unsigned char*)gx, strlen(gx), signret, siglen, (unsigned char*)publicKey1);
	if (ret)	cout << "Authentication successful" << endl;
	else cout << "Authentication failed" << endl;
	
	return 0;
}

Operation results

4. Use socket to realize communication between the two sides
WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//Create socket
	SOCKET clntSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

	//Send messages to the server and process address and other information
	sockaddr_in sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));			//Each byte is filled with 0
	sockAddr.sin_family = PF_INET;
	sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	sockAddr.sin_port = htons(8888);
	connect(clntSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
	//Receive server messages
	char szBuffer[0xffff] = { 0 };
	send(clntSock, ga, strlen(ga) + sizeof(char), NULL);
	recv(clntSock, szBuffer, 0xffff, NULL);//Define the size of the cache array received at one time in hexadecimal
	//Output received data
//	cout << "gy: " << szBuffer << endl;
	
	send(clntSock, unit, strlen(unit) + sizeof(char), NULL);									   	   
	//szBuffer[0xffff] = { 0 };
	recv(clntSock, szBuffer, 0xffff, NULL);
	char* pstring;
	char message[4][1024];
	pstring = strtok(szBuffer, "|");
	cout << "Received Bob Information about:" <<endl;
	int i = 0;
	while (pstring)
	{
		strcpy(message[i], pstring);
		i++;
		//printf("%s\n", pstring);
		pstring = strtok(NULL, "|");
	}
	printf("Bob Public key of gy: %s\n", message[0]);
	printf("Bob Identity of:%s\n", message[1]);
	printf("Bob Signature of:%s\n", message[2]);
	printf("Bob Summary of:%s\n", message[3]);
	//szBuffer[0xffff] = { 0 };
	send(clntSock, MACA, strlen(MACA) + sizeof(char), NULL);
	recv(clntSock, szBuffer, 0xffff, NULL);
	//Cout < < bobmac signature: "< szbuffer < < endl;
	//Close socket
	closesocket(clntSock);
	//Terminate dll
	WSACleanup();

Operation results

Topics: cryptology