Home

Pricing
Sort by
Enter a search query to start.

New here?
It's fast and easy to sign up, and you can start straight away.

Enter a Display Name
Enter your full name or a display name. Businesses, couples and families are also accepted.
Examples:
Model Trains Inc.,
Sam and Janis Allen
Enter a username
Username requirements:
• at least 6 characters long,
• can use letters and numbers,
• can not use spaces or
  other characters.
Examples:
mattsmith
7homes95
Password strength:
Your password can be up 250 characters in length and can contain letters, numbers, punctuation marks and spaces.
Hint: a secure password is long but easy to remember and not complex, e.g.
Jules Verne is an excellent author
Retype password
Enter the same password again to check for errors.
(Optional) Enter an email address
This is optional.
You can enter an email address to send account information to, such as password reset links.
The account email address is not shown publicly.

By signing up you agree to our Terms of Use & Privacy Policy

 

Welcome back.
Enter your account details below to continue.

Username
Password
 
Forgot password?

Enter your details below to send a password reset email.

Username of account to recover
Account Email
 

    Encrypting and Decrypting Data with OpenSSL

    Storing sensitive data is easier today thanks to a few lines of OpenSSL. In finding a secure way to store all sorts of passwords on a device for Thoth, we decided encrypting them with a master password was the way to go. Of course these methods aren't used just to store passwords, but for any situation where plain text or binary data would need to be securely stored.

    This post will show you how to use 128 bit AES in CBC mode, using the encryption function EVP_aes_128_cbc() which in short means:

    There are other encryption functions, listed in OpenSSL's EVP cipher modes or in more detail in OpenSSL's EVP manpage, but these other methods are an exercise left up to the reader. Also, OpenSSL can be either run as a command-line tool, or as a library for another app. We will be using the library functions from here on.

    Encryption Basics

    Setting up the encrypting environment is simple. We start by creating a cipher context which handles our encryption commands. The next step is to provide a key and an iv or initialization vector. The key is a byte sequence specific to a user-provided secret (usually a password), while the iv is a unique random array of bytes generated for the encryption process. Both the key and iv need to be at least the same size of the cipher block, which is 128 bits or 16 bytes of data in this example. Also, the same key and iv will need to be saved for later to decrypt the encrypted data.

    EVP_CIPHER_CTX *ctx;
    ctx = EVP_CIPHER_CTX_new();
    EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);

    Once the key and iv have been given, we can now encrypt a stream of data. In very long streams this can be broken up in chunks, but since we're only encrypting short strings we can do nearly all the encryption in one go. The additional variables for this function include:

    • outbuf - an array of unsigned chars to store the encrypted data in.
    • outlen - an unsigned integer to record how many bytes have been encrypted, incase it is less than the size of outbuf.
    • plaintext - the original text we want to encrypt. Its length is also provided as the last variable.
    EVP_EncryptUpdate(ctx, outbuf, &outlen, (guchar *)plaintext, strlen(plaintext));

    Remember how AES encrypts in 128 bit chunks? Sometimes the encrypted data doesn't exactly line up. The last function, "EncryptFinal" function finishes the encrypted stream cleanly and adds padding where there aren't enough bits to keep encrypting. The value in tmplen lets us know how much more data is added to the end.

    EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen);
    outlen += tmplen;
    EVP_CIPHER_CTX_free(ctx);

    And that's basically it! In outbuf we now have an encrypted byte sequence that is outlen bytes long.

    Wrapping Up

    The decryption process is basically the same, except we call the "Decrypt" function counterparts, and plaintext supplied to "EncryptUpdate" is the encrypted binary data instead.

    Of course this example only touches lightly on the full capabilities OpenSSL and other encryption libraries have in their toolkit, but this can at least provide a valuable stepping stone to anybody interested in how to encrypt and decrypt data. For more information the links at the top of this post can describe in detail the functions used throughout this demo.

    The complete code in included at the end of this post. To see it in action, copy the following lines of code to a file named crypdemo.c and compile it from the terminal with:

    gcc crypdemo.c -o crypdemo -lssl -lcrypto `pkg-config --cflags --libs glib-2.0 libcrypto`

    You will also need to have the glib and openssl libraries and development headers installed for this to compile and run.

    crypdemo.c

    /**
     * Crypt Demo: encrypt and decrypt a text string with 128bit AES.
     *
     * Usage: ./crypdemo [string to encrypt] [password] [initialization vector]
     *
     * "string to encrypt" is either a length of plain text to encrypt,
     *    usually enclosed in single quotes (') if using spaces,
     *    or it is a base64 encoded string of binary data encrypted with this demo.
     * "password" is a plain text password provided by the user (you).
     * "initialization vector" (shortened as "iv") is an optional base64 encoded
     *    string of binary data to use as the iv.
     *    If you provide an iv the demo will decrypt only. If you do not provide an iv
     *    the demo will generate one to encrypt the given string and immediately
     *    decrypt it after.
     *
     * Compile with:
     * gcc crypdemo.c -o crypdemo -lssl -lcrypto `pkg-config --cflags --libs glib-2.0 libcrypto`
     */
    
    #include <glib.h>
    #include <stdio.h>
    #include <string.h>
    #include <openssl/evp.h>
    #include <openssl/rand.h>
    
    /**
     * Encrypt a string of plain text and encode
     * the encrypted byte data as base64.
     */
    gchar *do_encrypt (char *plaintext, char *password, char *b64iv)
    {
        /* Allow enough space in output buffer for additional block */
        guchar outbuf[1024];
        int outlen, tmplen;
    
        gsize iv_size;
        guchar *iv = g_base64_decode(b64iv, &iv_size);
    
        /* Generate key (password) */
        /* Can't use password string here! Need to generate a byte sequence. */
        guchar key[256];
        PKCS5_PBKDF2_HMAC_SHA1((const gchar *)password, g_utf8_strlen(password, -1),
                NULL, 0, 1000, 128, key);
    
        EVP_CIPHER_CTX *ctx;
        ctx = EVP_CIPHER_CTX_new();
        EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    
        if (EVP_EncryptUpdate(ctx, outbuf, &outlen, (guchar *)plaintext,
                strlen(plaintext)) == 0) {
            printf("EVP_EncryptUpdate returned 0n");
            return 0; /* Error */
        }
    
        if(!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) {
            printf("EVP_EncryptFinal_ex returned 0n");
            return 0; /* Error */
        }
    
        outlen += tmplen;
        EVP_CIPHER_CTX_free(ctx);
    
        g_free(iv);
    
        /* Need to encode as base64 because encrypted data is binary. */
        gchar *str = g_base64_encode(outbuf, outlen);
        return str;
    }
    
    /**
     * Decrypt a base64 encoded encrypted byte sequence.
     */
    gchar *do_decrypt(char *base64data, char *password, char *base64iv)
    {
        printf("%d Decrypting with base64iv = %sn", __LINE__, base64iv);
    
        /* Decode IV (initalization data) */
        gsize iv_size;
        guchar *iv = g_base64_decode(base64iv, &iv_size);
    
        /* Decode base64 data to binary */
        gsize decoded_size;
        guchar *encdata = g_base64_decode(base64data, &decoded_size);
    
        /* Generate key (password) */
        /* Can't use password string here! Need to generate a byte sequence. */
        guchar key[256];
        PKCS5_PBKDF2_HMAC_SHA1((const gchar *)password, g_utf8_strlen(password, -1),
                NULL, 0, 1000, 128, key);
    
        /* Decrypt now */
        guchar outbuf[1024];
        int outlen, tmplen;
    
        EVP_CIPHER_CTX *ctx;
        ctx = EVP_CIPHER_CTX_new();
        EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
    
        if (EVP_DecryptUpdate(ctx, outbuf, &outlen, encdata, decoded_size) == 0) {
            printf("EVP_DecryptUpdate returned 0n");
            return 0; /* Error */
        }
    
        if(!EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen)) {
            printf("EVP_DecryptFinal_ex returned 0n");
            return 0; /* Error */
        }
    
        outlen += tmplen;
        EVP_CIPHER_CTX_free(ctx);
    
        g_free(encdata);
        g_free(iv);
    
        gchar *str = g_strndup(outbuf, outlen);
        return str;
    }
    
    /**
     *
     */
    int main (int argc, char *argv[])
    {
        if (argc < 2) {
               printf("Usage: %s [string] [password] [iv (optional)]n", argv[0]);
               printf("(Supplying an iv (initialization vector) changes the demo to decrypt only mode.n");
               exit(1);
        }
    
        gchar *base64iv;
        gchar *encstr = NULL;
        if (argv[3]) {
            /* If we're decrypting only, get the encrypted string
             * and iv from command-line */
            base64iv = g_strdup(argv[3]);
            encstr = g_strdup(argv[1]);
        } else {
            /* Otherwise we will supply the encrypted string
             * and generate a new iv here. */
            guchar *iv = g_malloc0(16);
            int rc = RAND_bytes(iv, 16);
            if (rc != 1) {
                printf("Can't get RAND_bytes.n");
                exit(1);
            }
            base64iv = g_base64_encode(iv, 16);
            printf("* * * Generated new iv (base64 encoded) = %s * * *n", base64iv);
            g_free(iv);
        }
    
        gchar *encpw = g_strdup(argv[2]);
        /* Only encrypt if no IV given. */
        if (!argv[3]) {
            encstr = do_encrypt(argv[1], encpw, base64iv);
            printf("Try decrypting with: %s '%s' %s '%s'n", argv[0], encstr, argv[2], base64iv);
        } 
        g_free(encpw);
    
        gchar *decpw = g_strdup(argv[2]);
        gchar *e = g_strdup(encstr);
        gchar *b64iv = g_strdup(base64iv);
    
        /* Always decrypt */
        gchar *decstr = do_decrypt(e, decpw, b64iv);
        printf("Decrypted text = %sn", decstr);
        g_free(decstr);
        g_free(decpw);
    
        g_free(e);
        g_free(b64iv);        
    
        exit(0);
    }
    Show full posts Show as thumbnails Show as list Sort by:
      Upload template file
    Enter keyword(s) to search.
    Reply ctrl enter
    Reply by email
    Cancel esc
    Click for advanced permissions.
    View
    Edit
    Reply
    Approve
    Moderate
    Tags
    Visibility
    Replies
    General
    Content Suitability
    Show Replies As
    Sort Replies By ·
      Paste Link Undo Redo ctrl enter

    Loading...

    Loading messages...

    Attach an image or file
    Cancel esc
    Cancel esc