0

In reference to my previous question I just have to change most part of the code and use function call. Now the file can read and print as expected, but I noticed that after when it goes to the expected fileReader and prints the file, it automatically exited by calling choiceReader(case: else ) function which is not the expected function to call. My expectation is that algorithm() will be the next call. Please what am I missing here again?

The new code is:

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int success = 0;
char counter[1000];//used to monitor the read file length
int c;

size_t cipher_len; // size_t is sizeof(type)
unsigned char* ciphertext;
unsigned char plainpassword[] = "00000";
unsigned char* password = &plainpassword[0];

unsigned char salt[8];

unsigned char key[16];
unsigned char iv[16];

FILE *fp;
FILE *fptr;

char* plaintext = "To be or not to be is the question.";
char dict[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

int decryptedtext_len, ciphertext_len, dict_len;

char* ciphertext_base64;

unsigned char *plaintexts;
int len;
int plaintext_len;

void handleOpenSSLErrors(void)
{
    ERR_print_errors_fp(stderr);
    abort();
}

unsigned char* decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv ){

    EVP_CIPHER_CTX *ctx;
    
    unsigned char* plaintext = malloc(ciphertext_len);
    bzero(plaintext,ciphertext_len);

    /* Create and initialise the context */
  
    if(!(ctx = EVP_CIPHER_CTX_new())) handleOpenSSLErrors();

    /* Initialise the decryption operation. IMPORTANT - ensure you use a key
    * and IV size appropriate for your cipher
    * IV size for *most* modes is the same as the block size. For AES this
    * is 128 bits */
    
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
        handleOpenSSLErrors();

  
    EVP_CIPHER_CTX_set_key_length(ctx, EVP_MAX_KEY_LENGTH);

    /* Provide the message to be decrypted, and obtain the plaintext output.
    * EVP_DecryptUpdate can be called multiple times if necessary
    */
    if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
        handleOpenSSLErrors();
   
    plaintext_len = len;

    /* Finalise the decryption. Further plaintext bytes may be written at
    * this stage.
    */
    
    // return 1 if decryption successful, otherwise 0
    if(1 == EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) 
        success = 1;
    plaintext_len += len;

   
    /* Add the null terminator */
    plaintext[plaintext_len] = 0;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);
    //delete [] plaintext;
    return plaintext;
}


size_t calcDecodeLength(char* b64input) {
    size_t len = strlen(b64input), padding = 0;

    if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
        padding = 2;
    else if (b64input[len-1] == '=') //last char is =
        padding = 1;
    return (len*3)/4 - padding;
}

void Base64Decode( char* b64message, unsigned char** buffer, size_t* length) {

    
    BIO *bio, *b64;  // A BIO is an I/O strean abstraction

    int decodeLen = calcDecodeLength(b64message);
    *buffer = (unsigned char*)malloc(decodeLen + 1);
    (*buffer)[decodeLen] = '\0';

    bio = BIO_new_mem_buf(b64message, -1);
    b64 = BIO_new(BIO_f_base64());
    bio = BIO_push(b64, bio);

    //BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
    *length = BIO_read(bio, *buffer, strlen(b64message));
    BIO_free_all(bio);
}

void initAES(const unsigned char *pass, unsigned char* salt, unsigned char* key, unsigned char* iv )
{
    //initialisatio of key and iv with 0
    bzero(key,sizeof(key)); 
    bzero(iv,sizeof(iv));
  
    EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, pass, strlen(pass), 1, key, iv);
}


int checkPlaintext(char* plaintext, char* result){

    int length = 10; // we just check the first then characters
    return strncmp(plaintext, result, length);

}

//this tries to crack the password.
int algorithm(){
    time_t begin = time(NULL);

    for(int i=0; i<dict_len; i++)
        for(int j=0; j<dict_len; j++)
            for(int k=0; k<dict_len; k++)
                for(int l=0; l<dict_len; l++)
                    for(int m=0; m<dict_len; m++){
                        *password = dict[i];
                        *(password+1) = dict[j];
                        *(password+2) = dict[k];
                        *(password+3) = dict[l];
                        *(password+4) = dict[m];

                        
                        initAES(password, salt, key, iv);
                        unsigned char* result = decrypt(ciphertext, cipher_len, key, iv);
                        
                        if (success == 1){
                            if(checkPlaintext(plaintext, result)==0){
                                
                                printf("Password is %s\n", password);
                                
                                time_t end = time(NULL);
                                printf("Time elpased is %ld seconds", (end - begin));
 
                                return 0;
                            }

                        }
                       
                        free(result);           
     }
}

// this given cipher text
int firstReader(){
    if ((fp = fopen("givenfile.txt", "r")) == NULL) {
        printf("Error! File cannot be opened.");
        exit(1);
    }
    fscanf(fp, "%[^\n]", counter);
    
    printf("Cipher text is:\n%s", counter);
    printf("\nCracking cipher text one in progress ....\n");

    algorithm();//calls the algorithm function
}

int secondReader(){

    if ((fptr = fopen("cipher1.txt", "r")) == NULL) {
    printf("Error! File cannot be opened.");
    // Program exits if the file pointer returns NULL.
    exit(1);
    }
    fscanf(fptr, "%[^\n]", counter);
    
    printf("Cipher text is:\n%s", counter);
    printf("\nCracking cipher text tow in progress ....\n");

    algorithm(); // calls the algorithm function

}

// reads user's choice and performs the next operation accordingly
void choiceReader(){

    printf("User's application guide.\nIst cipher decryption = 1\nSecond cipher decryption = 2\nQuit = Any other input\n");
    scanf("%d", &c);
    
    if(c==1){
        firstReader();
    }
    if(c==2){
        secondReader();
    }

    else{
        printf("Application Exited ...");
        exit(1);
    }

}

int main (void)
{
    //the core function that controls the user's action.
    choiceReader();

    dict_len = strlen(dict);

    if (c==1){
        ciphertext_base64 = (char*) fp;
    }
    if (c==2){
        ciphertext_base64 = (char*) fptr;
    }
    
    printf(ciphertext_base64);

    ERR_load_crypto_strings();
    
    Base64Decode(ciphertext_base64, &ciphertext, &cipher_len);

    
    // retrive the slater from ciphertext (binary)
    if (strncmp((const char*)ciphertext,"Salted__",8) == 0) { // find the keyword "Salted__"
        
        memcpy(salt,&ciphertext[8],8);
        ciphertext += 16; 
        cipher_len -= 16;
    
    }
            
    // Clean up
    fclose(fptr);
    EVP_cleanup();
    ERR_free_strings();


    return 0;
}

The output is screenshot below:

enter image description here

  • If you haven't learned how to use a debugger before, take this as the perfect opportunity for it. First try to just run the program in the debugger, to catch possible crashes (which is typically the reason for unexpected application exits like this). When it catches a crash, it can help you to locate where in your code it happens and also let you examine variables and their values to see if that can help you. – Some programmer dude Apr 22 '21 at 16:57
  • To continue from my previous comment... If it turns out to not be a crash, then you can use the debugger to step through your code statement by statement to see what really happens. And of course examine variables and see how their values change – Some programmer dude Apr 22 '21 at 17:00
  • On an unrelated note, the variable `password isn't needed, as arrays naturally decay to pointers to their first element. Using plain `plainpassword` will be exactly the same as `&plainpassword[0]`. – Some programmer dude Apr 22 '21 at 17:00
  • Thanks a lot for your time, someone actually fixed the error for me but the program crashed along the way without performing the algorithm() task. – Adeolu Temitope Olofintuyi Apr 22 '21 at 17:08

2 Answers2

1

You wrote:

    if(c==1){
        firstReader();
    }
    if(c==2){
        secondReader();
    }
    else{
        printf("Application Exited ...");
        exit(1);
    }

which means:

  • If c is 1, call firstReader.
  • If c is 2, call secondReader, otherwise exit.

If c is 1, then it calls firstReader, and then exits because c is not 2. The computer is not smart enough to figure out what you actually meant. You probably meant to write else if(c==2) which links the two ifs together so that the final else only runs if neither one is true.

user253751
  • 57,427
  • 7
  • 48
  • 90
0

Everything is perfectly working as expected now, the sequential error was simply due to the wrong logical call to the ciphertext_base64

Thanks everyone for your time and guide.