diff --git a/certexample.c b/certexample.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a9df3efacd48577abb96b844d3a72559b66e076
--- /dev/null
+++ b/certexample.c
@@ -0,0 +1,463 @@
+/**
+ Name: Shubham Jayswal
+ Login Id: sjayswal@student.unimelb.edu.au
+ Example certifcate code
+ gcc -o certexample certexample.c -lssl -lcrypto
+ */
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <stdio.h>
+#include <string.h>
+
+void read_csv(char *filename);
+int get_keylen(EVP_PKEY * pubkey);
+int validate_date(ASN1_TIME *to);
+int validate_cn(char *hostname, X509 *cert);
+int validate_ca(X509 *cert);
+int validate_san(char *hostname, X509 *cert);
+int validate_key_usage(X509 *cert);
+int is_subdomain(char *hostname);
+int sub_domain_match(char *hostname, char *wildcard);
+
+/**
+ * Returns 1 if the certificate is not for a CA
+ */
+int validate_ca(X509 *cert) {
+
+	X509_EXTENSION *ex = X509_get_ext(cert,
+			X509_get_ext_by_NID(cert, NID_basic_constraints, -1));
+	ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+	char buff[1024];
+	OBJ_obj2txt(buff, 1024, obj, 0);
+
+	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");
+	}
+	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_free_all(bio);
+	return (strcmp("CA:TRUE", buf) == 0);
+
+}
+
+/**
+ * Validates extended key usages.
+ *
+ * return 0 if valid
+ *        -1 if a code signing certificate has been used
+ *        -2 if a client certificate has been used.
+ *        -3 if the extendend usage info isn't clear
+ *        1 if there are multiple allowed usages which includes on a webserver
+ */
+int validate_key_usage(X509 *cert) {
+
+	X509_EXTENSION *ex = X509_get_ext(cert,
+			X509_get_ext_by_NID(cert, NID_ext_key_usage, -1));
+	ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+	char buff[1024];
+	OBJ_obj2txt(buff, 1024, obj, 0);
+
+	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");
+	}
+	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_free_all(bio);
+
+	if (strcmp(buf, "Code Signing") == 0) {
+		return -11;
+	}
+	if (strcmp(buf, "TLS Web Client Authentication") == 0) {
+		return -2;
+	}
+
+	if (strstr(buf, "Web Server Authentication") != NULL) {
+		/* Web Server Authentication is one of the supported usages, but are there any others? */
+		if (strstr(buf, ",") != NULL) {
+			return 1;
+		}
+		return 0;
+	}
+	return -3;
+}
+
+/**
+ * Return 0 when there is a perfect match between one of the SANs and the domain
+ *        1 when the SAN is a wildcard and there is a wildcard match
+ *        -1 When there is not SAN information
+ *        -2 When san information i present but we cannot match
+ */
+int validate_san(char *hostname, X509 *cert) {
+
+	GENERAL_NAMES *alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0,
+			0);
+	char *buf;
+
+	int len;
+	int i;
+	if (alt_names == NULL) {
+		return -1;
+	}
+
+	len = sk_GENERAL_NAME_num(alt_names);
+
+	for (i = 0; i < len; ++i) {
+		GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
+		if (name->type == GEN_DNS) {
+			buf = (char *) ASN1_STRING_data(name->d.dNSName);
+
+			if (buf[0] == '*' && is_subdomain(hostname)
+					&& sub_domain_match(hostname, buf)) {
+				printf("SAN WILDCARD %s %s\n", hostname, buf);
+				OPENSSL_free(buf);
+				return 1;
+			} else {
+				OPENSSL_free(buf);
+				return -2;
+			}
+
+		}
+	}
+
+	return -2;
+}
+
+/**
+ * Validate the given certificates date
+ *
+ * return 1 if the date is in the future, 0 if the date is current
+ * and -1 if the date is in the past.
+ *
+ *
+ */
+int validate_date(ASN1_TIME *to) {
+	int day, sec;
+	ASN1_TIME_diff(&day, &sec, NULL, to);
+
+	if (day > 0 || sec > 0) {
+		return 1;
+	}
+	if (day < 0 || sec < 0) {
+		return -1;
+	}
+
+	return 0;
+
+}
+
+/**
+ * Validates the common name
+ *
+ * Return 0 if there is an exact match.
+ *        1 if this is a wild card certificate and can be matched
+ *        -1 cannot be matched
+ *        -2 is a wild card but still cannot be matched because no sub domai.
+ */
+
+int validate_cn(char *hostname, X509 *cert) {
+
+	X509_NAME_ENTRY *common_name_entry = NULL;
+	ASN1_STRING *common_name_asn1 = NULL;
+	char *common_name_str = NULL;
+
+	int location = X509_NAME_get_index_by_NID(
+			X509_get_subject_name((X509 *) cert), NID_commonName, -1);
+	if (location >= 0) {
+		common_name_entry = X509_NAME_get_entry(
+				X509_get_subject_name((X509 *) cert), location);
+		if (common_name_entry != NULL) {
+			common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
+			if (common_name_asn1 != NULL) {
+				common_name_str = (char *) ASN1_STRING_data(common_name_asn1);
+
+				if (ASN1_STRING_length(common_name_asn1)
+						== strlen(common_name_str)) {
+					/* after a long drawn out process we have finaly got the common name as a string.
+					 * but we are not out of the woods yet.
+					 */
+					if (strcasecmp(hostname, common_name_str) == 0) {
+						/* all is well, we have an exact match */
+						return 0;
+					} else {
+						if (common_name_str[0] == '*') {
+							/* wildcard, we can find out if there is a subdomain by counting .. */
+
+							if (is_subdomain(hostname)
+									&& sub_domain_match(hostname,
+											common_name_str)) {
+
+								return 1;
+							} else {
+								return -2;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return -1;
+}
+
+/**
+ * Is there a wildcard match?
+ *
+ * 1 if true
+ */
+int sub_domain_match(char *hostname, char *wildcard) {
+	char *h = strstr(hostname, ".");
+	char *w = strstr(wildcard, ".");
+
+	return strcmp(h + 1, w + 1) == 0;
+}
+
+/**
+ * Does this hostname have a subdomain component.
+ */
+int is_subdomain(char *hostname) {
+	int i, count;
+	for (i = 0, count = 0; hostname[i] != '\0'; i++) {
+		if (hostname[i] == '.') {
+			count++;
+		}
+	}
+	return count > 1;
+}
+/**
+ * Gets the keylength in bits.
+ */
+int get_keylen(EVP_PKEY * pubkey) {
+	RSA * rsa;
+
+	rsa = EVP_PKEY_get1_RSA(pubkey);
+	int key_length = RSA_size(rsa);
+
+	free(rsa);
+	return key_length * 8;
+}
+
+void read_csv(char *filename) {
+
+	BIO *certificate_bio = NULL;
+	X509 *cert = NULL;
+	int key_len;
+
+	int domain_status;
+
+	char line[127];
+	int i = 0, j = 0, cmp, san_validation;
+	char site[64];
+	char file_name[64];
+
+	FILE *in = fopen(filename, "r");
+	FILE *out;
+
+	if (in != NULL) {
+		out = fopen("output.csv", "w");
+		if (out != NULL) {
+			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());
+
+			while (fscanf(in, "%s", line) > 0) {
+				/* first part of the code. We read the file_name to a pair, certificate file_name name and hostname */
+				for (i = 0; line[i] != '\0' && line[i] != ','; i++) {
+					file_name[i] = line[i];
+				}
+
+				file_name[i++] = '\0';
+
+				for (j = 0; line[i] != '\0' && line[i] != ','; i++) {
+					site[j++] = line[i];
+				}
+
+				site[j] = '\0';
+
+				if (!(BIO_read_filename(certificate_bio, file_name))) {
+					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);
+				}
+
+				/* now for the domain verification. This is the first step that we are peforming. */
+				domain_status = validate_cn(site, cert);
+
+				if (domain_status == -1) {
+					fprintf(out,
+							"%s,%s,%d,Invalid - domain does not match Common Name\n",
+							file_name, site, 0);
+					continue;
+				}
+				if (domain_status == -2) {
+					fprintf(out,
+							"%s,%s,%d,Invalid - wildcard Common Name requires subdomain \n",
+							file_name, site, 0);
+					continue;
+				}
+
+				if (validate_ca(cert)) {
+					/* failed the first test. This is for a CA */
+					fprintf(out, "%s,%s,%d,Invalid - marked as a CA\n",
+							file_name, site, 0);
+
+					continue; // continue is ugly but a huge chain of if else is uglier.
+
+				}
+
+				key_len = get_keylen(X509_get_pubkey(cert));
+				if (key_len < 2048) {
+					/* failed the second test, the keylen is too short */
+					fprintf(out,
+							"%s,%s,%d,Invalid because key size is too small (%d bits instead of >=2048)\n",
+							file_name, site, 0, key_len);
+					continue;
+				}
+
+				/* now we check the dates */
+				cmp = validate_date(X509_get_notBefore(cert));
+				if (cmp == 1) {
+					fprintf(out,
+							"%s,%s,%d,Invalid valid from date - date is in the future\n",
+							file_name, site, 0);
+					continue;
+				}
+
+				cmp = validate_date(X509_get_notAfter(cert));
+				if (cmp == -1) {
+
+					fprintf(out,
+							"%s,%s,%d,Invalid - certificate has expired - valid to date in the past\n",
+							file_name, site, 0);
+
+					continue;
+				}
+
+				/* now for key usage */
+				cmp = validate_key_usage(cert);
+
+				if (cmp == -11) {
+					fprintf(out,
+							"%s,%s,%d,Invalid - extended key usage is code signing only\n",
+							file_name, site, 0);
+					continue;
+				}
+				if (cmp == -2) {
+					fprintf(out,
+							"%s,%s,%d,Invalid - extended key usage is only for client authentication\n",
+							file_name, site, 0);
+					continue;
+
+				}
+
+				san_validation = validate_san(site, cert);
+
+				/**
+				 * Don't ask how i wrote this huge bunch of if else conditions. I don't know myself!!
+				 */
+				if (domain_status == 0) {
+					if (san_validation == 0) {
+						fprintf(out,
+								"%s,%s,1,Valid - all correct - domain matches Common Name or SAN wildcard\n",
+								file_name, site);
+					} else {
+						if (cmp == 1) {
+							fprintf(out,
+									"%s,%s,1,Valid - all correct - tests multiple extended key usage\n",
+									file_name, site);
+						} else {
+							if (san_validation == -1) {
+								fprintf(out,
+										"%s,%s,1,Valid correct key size; valid dates; not a CA; server authentication; domain matches Common Name\n",
+										file_name, site);
+							} else if (san_validation == 0) {
+
+								fprintf(out,
+										"%s,%s,1,Valid - all correct - domain matches Common Name and SAN\n",
+										file_name, site);
+							} else if (san_validation == 1) {
+								printf("%s %d %d\n", site, domain_status,
+										san_validation);
+								fprintf(out,
+										"%s,%s,1,Valid - all correct - domain matches Common Name or SAN wildcard\n",
+										file_name, site);
+							} else {
+								fprintf(out,
+										"%s,%s,1,Valid - all correct - domain matches Common Name and SAN\n",
+										file_name, site);
+							}
+
+						}
+					}
+				} else {
+					if (cmp == 0) {
+						if (san_validation == 1) {
+							fprintf(out,
+									"%s,%s,1,Valid - all correct - domain matches Common Name or SAN wildcard\n",
+									file_name, site);
+						} else {
+							if (san_validation == -1) {
+								fprintf(out,
+										"%s,%s,1,Valid - all correct - domain matches through Common Name wildcard No SAN\n",
+										file_name, site);
+							}
+						}
+					} else {
+						fprintf(out,
+								"%s,%s,1,Valid - all correct - tests multiple extended key usage\n",
+								file_name, site);
+					}
+
+				}
+
+			}
+		} else {
+			printf("Couldn't create output file_name\n");
+		}
+	} else {
+		printf("File not found\n");
+	}
+
+	X509_free(cert);
+	BIO_free_all(certificate_bio);
+
+}
+
+int main(int argc, char *argv[]) {
+	if (argc != 2) {
+		printf("Incorrect number of arguments\n");
+		return 1;
+	}
+	read_csv(argv[1]);
+	return 0;
+}