diff --git a/.remote-sync.json b/.remote-sync.json
new file mode 100644
index 0000000000000000000000000000000000000000..2d3e8f5b6c1d7e44caca6963a2e6402441eb06ce
--- /dev/null
+++ b/.remote-sync.json
@@ -0,0 +1,14 @@
+{
+  "transport": "scp",
+  "uploadOnSave": true,
+  "useAtomicWrites": true,
+  "deleteLocal": false,
+  "hostname": "ubuntu@115.146.95.37",
+  "ignore": [
+    ".remote-sync.json",
+    ".git/**"
+  ],
+  "watch": [],
+  "keyfile": "~/Desktop/private.txt",
+  "passphrase": "j0nas13"
+}
\ No newline at end of file
diff --git a/certexample b/certexample
new file mode 100755
index 0000000000000000000000000000000000000000..133b4413ab264e369a804e79ee90672329bf6e0f
Binary files /dev/null and b/certexample differ
diff --git a/certexample.c b/certexample.c
index f525abae5b3580cc348e3088a7a441c860751e4b..ab7dba11f5a4eb06162b95618e19b56559a40553 100644
--- a/certexample.c
+++ b/certexample.c
@@ -3,70 +3,173 @@
     gcc -o certexample certexample.c -lssl -lcrypto
 */
 #include <openssl/x509.h>
+#include <openssl/asn1.h>
+#include <openssl/crypto.h>
+#include <openssl/asn1t.h>
 #include <openssl/x509v3.h>
 #include <openssl/bio.h>
 #include <openssl/pem.h>
 #include <openssl/err.h>
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <openssl/asn1_mac.h>
 
-int main()
-{
+const ASN1_TIME *X509_get0_notBefore(const X509 *x);
+char** str_split(const char* a_str, const char a_delim);
+char* concat(char *s1, char *s2);
+char* get_basic_constraints(X509 *cert);
+char* get_key_usage(X509 *cert);
+char* compare_not_before(X509 *cert);
+char* compare_not_after(X509 *cert);
+char* get_SAN(X509 *cert);
+char *get_domain_name(X509 *cert);
+int matches_subject_alternative_name(const char *hostname, X509 *server_cert);
+int get_public_key_length(X509 *cert);
+int validate_basic_constraints(char* basic_constraints);
+int validate_key_usage(char* key_usage);
+int validate_key_length(int length);
+int validate_CN(const char* hostname, char*cn);
+int validate_wildcard_string(const char *hostname, char*hostname_with_wildcard);
+int validate_CN_and_SAN(const char *url, X509 *cert);
+int validate_not_before(X509 *cert);
+int validate_not_after(X509 *cert);
+int validate_certificate(const char *url, X509 *cert);
 
-    const char test_cert_example[] = "./cert-file2.pem";
-    BIO *certificate_bio = NULL;
-    X509 *cert = NULL;
-    X509_NAME *cert_issuer = NULL;
-    X509_CINF *cert_inf = NULL;
-    STACK_OF(X509_EXTENSION) * ext_list;
+int main(int argc, char **argv){
+    int LINE_BUFFER=100;
+    char line[LINE_BUFFER];
 
-    //initialise openSSL
+    FILE *csv_input = fopen(concat("./sample_certs/",argv[1]), "r");
+    FILE *csv_output = fopen("output_test.csv" ,"w");
+
+    //for each line in the csv file, process each certificate
     OpenSSL_add_all_algorithms();
     ERR_load_BIO_strings();
     ERR_load_crypto_strings();
 
-    //create BIO object to read certificate
-    certificate_bio = BIO_new(BIO_s_file());
+    int n = 0;
+    while (fgets(line, LINE_BUFFER, csv_input) != NULL){
+
+        printf("CSV LINE # %d\n", n);
+        BIO *certificate_bio = NULL;
+        X509 *cert = NULL;
+        X509_NAME *cert_issuer = NULL;
+        X509_CINF *cert_inf = NULL;
+        STACK_OF(X509_EXTENSION) * ext_list;
+        certificate_bio = BIO_new(BIO_s_file());
+        //here we are able to access each line
+        line[strlen(line)-1] = '\0';
+
+
+        char **csv_row_elements = str_split(line, ',');
+
+        printf("\tFILE: %s\n",csv_row_elements[0]);
+        printf("\tURL: %s\n",csv_row_elements[1]);
+
+
+        char *certificate_file = concat("./sample_certs/", csv_row_elements[0]);
+
+        const char *url = csv_row_elements[1];
+        //for some reason splitting keeps mututating the original string
+        char *unchanged_url = csv_row_elements[1];
+
+        FILE *fp = fopen(certificate_file, "r");
+
+        if (!(BIO_read_filename(certificate_bio, certificate_file))){
+            fprintf(stderr, "Error in reading cert BIO filename");
+            exit(EXIT_FAILURE);
+        }
+
+        //load certiifcate
+        if (!(cert = PEM_read_bio_X509(certificate_bio, NULL, 0, NULL))){
+            fprintf(stderr, "Error in loading certificate");
+            exit(EXIT_FAILURE);
+        }
+        // printf ("\tBASIC CONSTRAINT: %s\n",get_basic_constraints(cert));
+        // printf ("\tBASIC CONSTRAINT VALIDATION: %d\n",validate_basic_constraints(get_basic_constraints(cert)));
+        //
+        // // printf ("\tKEY USAGE: %s\n",get_key_usage(cert));
+        // printf ("\tKEY USAGE VALIDATION: %d\n",validate_key_usage(get_key_usage(cert)));
+        //
+        // // printf ("\tKEY LENGTH BITS: %d\n",get_public_key_length(cert));
+        //
+        // printf ("\tKEY LENGTH VALIDATION: %d\n",validate_key_length(get_public_key_length(cert)));
+        //
+        // // printf ("\tNot Before compared to Current:  %s\n",compare_not_before(cert));
+        // // printf ("\tNot After compared to Current:  %s\n",compare_not_after(cert));
+        // printf("\tNOT BEFORE VALIDATION %d\n", validate_not_before(cert));
+        // printf("\tNOT AFTER VALIDATION %d\n", validate_not_after(cert));
+        // // printf ("\tCommon Name:  %s\n",get_domain_name(cert));
+        //
+        // printf("\tCOMMON NAME AND SAN VALIDATION %d\n", validate_CN_and_SAN(url, cert));
+        // printf ("%d", 0 || 1);
+        // printf("FINAL VALIDATION %d\n", validate_certificate(url, cert));
+        // printf("\t%s\n", unchanged_url);
+        fprintf(csv_output,"%s,", csv_row_elements[0]);
+        fprintf(csv_output,"%s,", unchanged_url);
+        fprintf(csv_output,"%d\n", validate_certificate(url, cert));
+
+        // printf ("\tCOMMON NAME VALIDATION:  %d\n",);
+        // printf ("\tMatches Subject Alternative Name Result:  %d\n",);
+        // printf("URL: %s\n",url);
+
+        //
+        // printf("URL: %s\n",url);
+        n++;
 
-    //Read certificate into BIO
-    if (!(BIO_read_filename(certificate_bio, test_cert_example)))
-    {
-        fprintf(stderr, "Error in reading cert BIO filename");
-        exit(EXIT_FAILURE);
-    }
-    if (!(cert = PEM_read_bio_X509(certificate_bio, NULL, 0, NULL)))
-    {
-        fprintf(stderr, "Error in loading certificate");
-        exit(EXIT_FAILURE);
     }
+    exit(0);
+}
+char* get_basic_constraints(X509 *cert){
 
-    //cert contains the x509 certificate and can be used to analyse the certificate
-    
-    //*********************
-    // Example code of accessing certificate values
-    //*********************
+    X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_basic_constraints, -1));
 
-    cert_issuer = X509_get_issuer_name(cert);
-    char issuer_cn[256] = "Issuer CN NOT FOUND";
-    X509_NAME_get_text_by_NID(cert_issuer, NID_commonName, issuer_cn, 256);
-    printf("Issuer CommonName:%s\n", issuer_cn);
+    ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+
+    char buff[1024];
+    OBJ_obj2txt(buff, 1024, obj, 0);
+    //printf("Extension: %s, ", buff);
+
+    BUF_MEM *bptr = NULL;
+    char *buf = NULL;
+
+    BIO *bio = BIO_new(BIO_s_mem());
+
+    X509V3_EXT_print(bio, ex, 0, 0);
+
+
+    BIO_flush(bio);
+    BIO_get_mem_ptr(bio, &bptr);
+
+    //bptr->data is not NULL terminated - add null character
+    buf = (char *)malloc((bptr->length + 1) * sizeof(char));
+    memcpy(buf, bptr->data, bptr->length);
+    buf[bptr->length] = '\0';
+    BIO_flush(bio);
+    //Can print or parse value
+
+    return buf;
+}
+char* get_key_usage(X509 *cert){
+
+    X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_ext_key_usage, -1));
 
-    //List of extensions available at https://www.openssl.org/docs/man1.1.0/crypto/X509_REVOKED_get0_extensions.html
-    //Need to check extension exists and is not null
-    X509_EXTENSION *ex = X509_get_ext(cert, X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1));
     ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+
     char buff[1024];
     OBJ_obj2txt(buff, 1024, obj, 0);
-    printf("Extension:%s\n", buff);
+    //printf("Extension: %s, ", buff);
 
     BUF_MEM *bptr = NULL;
     char *buf = NULL;
 
     BIO *bio = BIO_new(BIO_s_mem());
-    if (!X509V3_EXT_print(bio, ex, 0, 0))
-    {
-        fprintf(stderr, "Error in reading extensions");
-    }
+
+    X509V3_EXT_print(bio, ex, 0, 0);
+
+
     BIO_flush(bio);
     BIO_get_mem_ptr(bio, &bptr);
 
@@ -76,15 +179,273 @@ int main()
     buf[bptr->length] = '\0';
 
     //Can print or parse value
-    printf("%s\n", buf);
 
-    //*********************
-    // End of Example code
-    //*********************
+    return buf;
+}
+int get_public_key_length(X509 *cert){
 
-    X509_free(cert);
-    BIO_free_all(certificate_bio);
-    BIO_free_all(bio);
-    free(buf);
-    exit(0);
-}
\ No newline at end of file
+    EVP_PKEY *public_key = X509_get_pubkey(cert);
+
+    RSA *rsa_key = EVP_PKEY_get1_RSA(public_key);
+
+    int key_length_bytes = RSA_size(rsa_key);
+
+    return (key_length_bytes*8);
+
+}
+char* get_domain_name(X509 *cert){
+    X509_NAME *x509_name = X509_get_subject_name(cert);
+    char *cert_cn = X509_NAME_oneline(x509_name, 0, 0);
+    cert_cn =(cert_cn+1);
+    char **chain = str_split(cert_cn, '/');
+    char *domain = chain[5];
+
+    char **domain_clean = str_split(domain, '=');
+
+    return domain_clean[1];
+}
+char* compare_not_before(X509 *cert){
+    int day, sec;
+    const ASN1_TIME *not_before = X509_get_notBefore(cert);
+
+    if (!ASN1_TIME_diff(&day, &sec, NULL, not_before)){
+        /* Invalid time format */
+        printf("what the fuck do now\n");
+    }
+
+    if (day > 0 || sec > 0){
+        return "Later";
+    }
+    else if (day < 0 || sec < 0){
+        return "Sooner";
+    }
+    else{
+        return "Same";
+    }
+    return "invalid?";
+}
+char* compare_not_after(X509 *cert){
+    int day, sec;
+    const ASN1_TIME *not_after = X509_get_notAfter(cert);
+
+    if (!ASN1_TIME_diff(&day, &sec, NULL, not_after)){
+        /* Invalid time format */
+        printf("what the fuck do now\n");
+    }
+
+    if (day > 0 || sec > 0){
+        return "Later";
+    }
+    else if (day < 0 || sec < 0){
+        return "Sooner";
+    }
+    else{
+        return "Same";
+    }
+
+    return "invalid?";
+}
+char* concat(char *s1, char *s2){
+	//concats two strings
+    char *result = malloc(strlen(s1)+strlen(s2)+1);
+    strcpy(result, s1);
+    strcat(result, s2);
+    return result;
+
+}
+char** str_split(const char* a_str, const char a_delim){
+    char** result = 0;
+    size_t count = 0;
+    char* tmp = (char *)a_str;
+    char* copy = (char *)a_str;
+    char* last_comma = 0;
+    char delim[2];
+    delim[0] = a_delim;
+    delim[1] = 0;
+
+    /* Count how many elements will be extracted. */
+    while (*tmp){
+        if (a_delim == *tmp){
+            count++;
+            last_comma = tmp;
+        }
+        tmp++;
+    }
+    /* Add space for trailing token. */
+    count += last_comma < (a_str + strlen(a_str) - 1);
+    /* Add space for terminating null string so caller
+       knows where the list of returned strings ends. */
+    count++;
+    result = malloc(sizeof(char*) * count);
+    if (result){
+        size_t idx  = 0;
+        char* token = strtok(copy, delim);
+
+        while (token){
+            assert(idx < count);
+            *(result + idx++) = strdup(token);
+            token = strtok(0, delim);
+        }
+        assert(idx == count - 1);
+        *(result + idx) = 0;
+    }
+    return result;
+}
+int matches_subject_alternative_name(const char *hostname, X509 *server_cert) {
+
+
+    int i;
+    int san_names_nb = -1;
+    STACK_OF(GENERAL_NAME) *san_names = NULL;
+
+    // Try to extract the names within the SAN extension from the certificate
+    san_names = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
+
+
+    if (san_names == NULL) {
+
+        return 0;
+    }
+
+    san_names_nb = sk_GENERAL_NAME_num(san_names);
+
+    // Check each name within the extension
+    for (i=0; i<san_names_nb; i++) {
+        const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
+
+        if (current_name->type == GEN_DNS) {
+            // Current name is a DNS name, let's check it
+            char *dns_name = (char *) ASN1_STRING_data(current_name->d.dNSName);
+            printf ("\t%s\n", dns_name);
+            // Make sure there isn't an embedded NUL character in the DNS name
+            if (ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
+
+                return 0;
+                break;
+            }
+            else { // Compare expected hostname with the DNS name
+
+
+
+                if (validate_wildcard_string(hostname, dns_name) == 1) {
+
+                    return 1;
+
+                    break;
+                }
+            }
+        }
+    }
+    sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
+    return 0;
+}
+int validate_key_usage(char* key_usage){
+
+    //key usage may be a bunch of strings, need to get first one if this is the case
+
+    if(strlen("TLS Web Server Authentication")!=strlen(key_usage)){
+        char **key_usage_clean = str_split(key_usage, ',');
+        if(strcmp(key_usage_clean[0], "TLS Web Server Authentication") == 0){
+            return 1;
+        }
+
+        return 0;
+
+
+    }
+
+    else{
+        if(strcmp(key_usage, "TLS Web Server Authentication") == 0){
+            return 1;
+        }
+        return 0;
+    }
+
+}
+int validate_basic_constraints(char* basic_constraints){
+
+    if(strcmp(basic_constraints, "CA:FALSE")==0){
+        // printf("\tBASIC CONSTRAINT PASS\n");
+        return 1;
+    }
+    return 0;
+}
+
+int validate_wildcard_string(const char *hostname, char*hostname_with_wildcard){
+    char **hostname_with_wildcard_split = str_split(hostname_with_wildcard, '.');
+
+    char **hostname_split = str_split(hostname, '.');
+
+    const char *hostname_with_wildcard_right = hostname_with_wildcard_split[1];
+    const char *hostname_split_right = hostname_split[1];
+
+    if(strcasecmp(hostname_split_right, hostname_with_wildcard_right)==0){
+        printf("\t\tWILDCARD FUNCTION\t\t%s == %s\n", hostname_split_right, hostname_with_wildcard_right);
+        return 1;
+    }
+    return 0;
+}
+int validate_key_length(int length){
+    if (length==2048){
+        return 1;
+    }
+    return 0;
+}
+int validate_CN(const char* hostname, char*cn){
+    if(cn[0]=='*'){
+        return (validate_wildcard_string(hostname, cn));
+    }
+    else{
+        if(strcasecmp(cn, hostname)==0){
+            return 1;
+        }
+        else{
+            return 0;
+        }
+    }
+    return 0;
+}
+int validate_CN_and_SAN(const char *url, X509 *cert){
+
+    if(validate_CN(url, get_domain_name(cert)) || matches_subject_alternative_name(url, cert)){
+        return 1;
+    }
+    else{return 0;}
+}
+int validate_not_before(X509 *cert){
+
+    if(strcmp(compare_not_before(cert), "Sooner")==0){
+        return 1;
+    }
+    return 0;
+}
+int validate_not_after(X509 *cert){
+
+    if(strcmp(compare_not_after(cert), "Later")==0){
+        return 1;
+    }
+    return 0;
+}
+int validate_certificate(const char *url, X509 *cert){
+    // printf ("\tBASIC CONSTRAINT VALIDATION: %d\n",validate_basic_constraints(get_basic_constraints(cert)));
+    // printf ("\tKEY USAGE VALIDATION: %d\n",validate_key_usage(get_key_usage(cert)));
+    // printf ("\tKEY LENGTH VALIDATION: %d\n",validate_key_length(get_public_key_length(cert)));
+    // printf("\tNOT BEFORE VALIDATION %d\n", validate_not_before(cert));
+    // printf("\tNOT AFTER VALIDATION %d\n", validate_not_after(cert));
+    // printf("\tCOMMON NAME AND SAN VALIDATION %d\n", validate_CN_and_SAN(url, cert));
+
+    int a =  validate_basic_constraints(get_basic_constraints(cert));
+    int b = validate_key_usage(get_key_usage(cert));
+    int c = validate_key_length(get_public_key_length(cert));
+    int d = validate_not_before(cert);
+    int e = validate_not_after(cert);
+    // printf("%s\n", url);
+    int f = validate_CN_and_SAN(url, cert);
+    // & b & c & d & e & f
+    if(a&b & c & d & e& f){
+        return 1;
+    }
+    else{
+        return 0;
+    }
+}
diff --git a/makefile b/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f62ae4ab0424f650456b5a46205d6e7776f81b01
--- /dev/null
+++ b/makefile
@@ -0,0 +1,3 @@
+#!/bin/bash
+all: certexample.c
+	gcc -I /usr/local/opt/openssl/include -L /usr/local/opt/openssl/lib -o certexample certexample.c -lssl -lcrypto
diff --git a/output_test.csv b/output_test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..7b25d86d602b3f7f1458ff4dff09f48859ffb099
--- /dev/null
+++ b/output_test.csv
@@ -0,0 +1,13 @@
+testone.crt,www.example.com,0
+testtwo.crt,www.mydomain.com,1
+testthree.crt,www.test.com,0
+testfour.crt,www.oldsite.com,0
+testfive.crt,www.unimelb.com,0
+testsix.crt,www.codetest.com,0
+testseven.crt,www.example.com,1
+testeight.crt,www.comp30023.com,1
+testnine.crt,www.certtest.com,1
+testten.crt,www.victoria.com,1
+testeleven.crt,freeca.com,0
+testtwo.crt,www.example.com,0
+testseven.crt,example.com,0
diff --git a/sample_certs/sample_input_single.csv b/sample_certs/sample_input_single.csv
new file mode 100644
index 0000000000000000000000000000000000000000..9239412f17ebe17cb8356c2f64a2cba45d93bd19
--- /dev/null
+++ b/sample_certs/sample_input_single.csv
@@ -0,0 +1 @@
+testeight.crt,www.comp30023.com