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
- 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
- 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)
- 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>
-
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 -
Configuration environment
- VC + + Directory - > including directory and Library Directory
- Linker - > Input - > Add dependency: enter ssleay lib,libeay.lib
- Put libeay32.0 in the openssl folder DLL and ssleay32 DLL file is in the folder where the project is located
- 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 cppextern "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 prototype | Function 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