diff --git a/.gitignore b/.gitignore
index 6537fabafe8f5041b46e388d19119b9d61b574c2..e947cd55b74438eb8a52544b3512bfc61bd0f993 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-**/.vscode
\ No newline at end of file
+**/.vscode
+**/test.*
\ No newline at end of file
diff --git a/README.md b/README.md
index 4aba1da8614891c78e1a729cb614586a0942de34..4f2620e25cf8743e6f295da6a975d60305e99163 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,14 @@
 # COMP30023 2019 Project 2
 
 ## Reference
-part [scp on Linux] from lab 9
+1. Modular Exponentiation algorithm
+    https://en.wikipedia.org/wiki/Modular_exponentiation
+
+2. 'client.c'
+    from lab 5
+
+3. scp on Linux
+    from lab 9
 
 ## Acknowledgement
 This project completed by Xun Zhang (854776)
\ No newline at end of file
diff --git a/dh.c b/dh.c
index 10c797b9ea5ca90128cc9fea9b57e24ab1150816..71cd9c4252813b74e3b3f2abb2b750d5d8af345d 100644
--- a/dh.c
+++ b/dh.c
@@ -1,11 +1,181 @@
 // Header files
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 // constants
+#define HOSTNAME "172.26.37.44"
+#define PORT 7800
+#define COMMAND "openssl sha256 dh.c"
+#define RESULT_TITLE "SHA256(dh.c)= "
+#define RESULT_TITLE_LEN 14
+#define BUFFERSIZE 256
+#define MESSAGE_ENDING '\n'
+#define USERNAME "xunz4"
+#define g_Value 15
+#define p_Value 97
 
 // methods reference
-
+int get_b_Value(char* hashresult);
+int calculate(int base, int pow, int modulus);
 
 int main(int argc, char** argv) {
-    
+    // used to save message
+    char buffer[BUFFERSIZE];
+
+    int b_Value;
+
+    // get b value
+    FILE* fp;
+    fp = popen(COMMAND, "r");
+    memset(buffer, '\0', BUFFERSIZE);
+    if (fgets(buffer, sizeof(buffer), fp) != NULL && strstr(buffer, RESULT_TITLE) != NULL) {
+        char* hashresult = strstr(buffer, RESULT_TITLE) + RESULT_TITLE_LEN;
+        bValue = get_b_Value(hashresult);
+    }
+
+    // connect to server
+    int sockfd;
+    struct sockaddr_in serv_addr;
+    struct hostent* server;
+
+    // build server
+    server = gethostbyname(HOSTNAME);
+
+    if (server == NULL) {
+        fprintf(stderr, "ERROR, no such host\n");
+        exit(0);
+    }
+
+    // Building data structures for socket
+
+    memset((char*)&serv_addr, '\0', sizeof(serv_addr));
+
+    serv_addr.sin_family = AF_INET;
+
+    bcopy(server->h_addr_list[0], (char*)&serv_addr.sin_addr.s_addr,
+          server->h_length);
+
+    serv_addr.sin_port = htons(PORT);
+
+    /* Create TCP socket -- active open
+     * Preliminary steps: Setup: creation of active open socket
+     */
+
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+    if (sockfd < 0) {
+        perror("ERROR opening socket");
+        exit(0);
+    }
+
+    if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
+        perror("ERROR connecting");
+        exit(0);
+    }
+
+    // Do processing
+    // send username
+    memset(buffer, '\0', BUFFERSIZE);
+
+    strcpy(buffer, USERNAME);
+    buffer[strlen(buffer)] = MESSAGE_ENDING;
+
+    n = write(sockfd, buffer, strlen(buffer));
+
+    if (n < 0) {
+        perror("ERROR writing to socket");
+        exit(0);
+    }
+
+    // send g^b (mod p)
+    memset(buffer, '\0', BUFFERSIZE);
+
+    int B = calculate(g_Value, b_Value, p_Value);
+    sprintf(buffer, "%d", B);
+    buffer[strlen(buffer)] = MESSAGE_ENDING;
+
+    n = write(sockfd, buffer, strlen(buffer));
+
+    if (n < 0) {
+        perror("ERROR writing to socket");
+        exit(0);
+    }
+
+    // receive g^a (mod p)
+    memset(buffer, '\0', BUFFERSIZE);
+
+    n = read(sockfd, buffer, BUFFERSIZE - 1);
+
+    if (n < 0) {
+        perror("ERROR reading from socket");
+        exit(0);
+    }
+
+    int A = atoi(buffer);
+
+    // send key A^b (mod p)
+    memset(buffer, '\0', BUFFERSIZE);
+
+    int keyB = calculate(A, b_Value, p_Value);
+    sprintf(buffer, "%d", keyB);
+    buffer[strlen(buffer)] = MESSAGE_ENDING;
+
+    n = write(sockfd, buffer, strlen(buffer));
+
+    if (n < 0) {
+        perror("ERROR writing to socket");
+        exit(0);
+    }
+
+    // receive status report
+    memset(buffer, '\0', BUFFERSIZE);
+
+    n = read(sockfd, buffer, BUFFERSIZE - 1);
+
+    if (n < 0) {
+        perror("ERROR reading from socket");
+        exit(0);
+    }
+
+    return 0;
+}
+
+/* get the hashresult string and convert the rst two hexadecimal digits to an
+ * integer
+ */
+int get_b_Value(char* hashresult) {
+    char substring[3];
+    memset(substring, '\0', sizeof(substring));
+    strncpy(substring, hashresult, 2);
+
+    int hex;
+    sscanf(substring, "%x", &hex);
+
+    return hex;
+}
+
+/* Since the limit of int, we have to use supplement function which applying
+ * Modular Exponentiation algorithm for the calculation of g^b (modp)
+ */
+int calculate(int base, int pow, int modulus) {
+    int odd;
+    int output = 1;
+
+    while (pow > 0) {
+        odd = pow % 2;
+
+        if (odd) output = (output * base) % modulus;
+        base = base * base % modulus;
+
+        pow = pow / 2;
+    }
+
+    return output;
 }
\ No newline at end of file
diff --git a/doc/client.c b/doc/client.c
new file mode 100644
index 0000000000000000000000000000000000000000..e40a70320936c180769b3b9470db602c0a35ef9e
--- /dev/null
+++ b/doc/client.c
@@ -0,0 +1,96 @@
+/* A simple client program for server.c
+
+   To compile: gcc client.c -o client
+
+   To run: start the server, then the client */
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+    int sockfd, portno, n;
+    struct sockaddr_in serv_addr;
+    struct hostent *server;
+
+    char buffer[256];
+
+    if (argc < 3) {
+        fprintf(stderr, "usage %s hostname port\n", argv[0]);
+        exit(0);
+    }
+
+    portno = atoi(argv[2]);
+
+    /* Translate host name into peer's IP address ;
+     * This is name translation service by the operating system
+     */
+    server = gethostbyname(argv[1]);
+
+    if (server == NULL) {
+        fprintf(stderr, "ERROR, no such host\n");
+        exit(0);
+    }
+
+    /* Building data structures for socket */
+
+    bzero((char *)&serv_addr, sizeof(serv_addr));
+
+    serv_addr.sin_family = AF_INET;
+
+    bcopy(server->h_addr_list[0], (char *)&serv_addr.sin_addr.s_addr,
+          server->h_length);
+
+    serv_addr.sin_port = htons(portno);
+
+    /* Create TCP socket -- active open
+     * Preliminary steps: Setup: creation of active open socket
+     */
+
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+    if (sockfd < 0) {
+        perror("ERROR opening socket");
+        exit(0);
+    }
+
+    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+        perror("ERROR connecting");
+        exit(0);
+    }
+
+    /* Do processing
+     */
+
+    printf("Please enter the message: ");
+
+    bzero(buffer, 256);
+
+    fgets(buffer, 255, stdin);
+
+    n = write(sockfd, buffer, strlen(buffer));
+
+    if (n < 0) {
+        perror("ERROR writing to socket");
+        exit(0);
+    }
+
+    bzero(buffer, 256);
+
+    n = read(sockfd, buffer, 255);
+
+    if (n < 0) {
+        perror("ERROR reading from socket");
+        exit(0);
+    }
+
+    printf("%s\n", buffer);
+
+    return 0;
+}