> -----Original Message-----
> From: [EMAIL PROTECTED]
> [mailto:[EMAIL PROTECTED] On Behalf Of Shaw Graham George
> Sent: Wednesday, March 12, 2008 6:01 PM
> To: [email protected]
> Subject: RE: crypto library in openssl
>
>
> Encrypted values are byte arrays, not strings.  They may
> contain null characters.  So you can't use strlen().  It's a
> common error.

But how to explain that passwords like "$dlkins02", "$flkins02", and 
"$Elkins02" can be decrypted correctly? Only "$elkins02" is decrypted into 
empty string.

To be more specific, this is the code to decrypt:
============================================================
bool_t esscrypto_decryptString(unsigned char *toDecrypt,
                               unsigned char *passPhrase,
                               int  sizeOfStrToDecrypt,
                               int  maxDecryptedStringSize,
                               int  *sizeOfDecryptedString,
                               unsigned char **decryptedString)
{
    EVP_CIPHER_CTX openSSLDecryptionStructure;
    int tempOutputLength = 0;
    int i = 0;
    int tmpOutputBufferPosition = 0;
    int tmpOffset = 0;
    char *tempPassPhrase = NULL;
    int currentDecryptedStrLength = 0;
    char *tempPtr = NULL;

    LOGLIBENTER(__FUNCTION__);

    tempPtr = ess_crypto_get_hex_string_from_string(toDecrypt);
    if (tempPtr != NULL)
    {
        LOGFORCE("Decrypting string (in hex) [%s]", tempPtr);
        free(tempPtr);
    }

    /* initialize return values */
    *sizeOfDecryptedString = 0;
    *decryptedString = NULL;

    /*
     * Paranoia, if we get "really" big strings to decrypt, we should reject
     *  them in favor of a buffered string decryption  method (like what is
     *  done for files).  So spit out a warning and return false.
     ******/
    if ( sizeOfStrToDecrypt > ESS_CRYPTO_MAX_TO_DECRYPT_STR_SIZE )
    {
        LOGWARN("Decrypting string of size [%d] is too big to decrypt",
                                                         sizeOfStrToDecrypt);
        LOGLIBRETURN(__FUNCTION__);
        return (FALSE);
    }

    tempPassPhrase = essCrypto_setupPassPhrase(passPhrase);

    if (tempPassPhrase == NULL)
    {
        LOGWARN("PassPhrase is null");
        LOGLIBRETURN(__FUNCTION__);
        return(FALSE);
    }

     EVP_DecryptInit(&openSSLDecryptionStructure, EVP_des_cbc(), tempPassPhrase,
                                                                (char *) NULL);

    /****
    * Since we are using DES, we don't need to set the key length always
       set to 64 bits, but if we use other ciphers, we need to do the following:
       EVP_CIPHER_CTX_set_key_length(&openSSLDecryptionStructure, <size>);
       // re-init
       EVP_DecryptInit(&openSSLDecryptionStructure, NULL, passPhrase,
                          (char *)NULL);
    ****/
    tempOutputLength = sizeOfStrToDecrypt +
                     EVP_CIPHER_CTX_block_size(&openSSLDecryptionStructure) + 1;

    /*
     * If the caller put in a non-negative or zero value for the max decrypted
     *  size, then the caller cares about how big of a string will be returned
     *  to it.  So check to make sure it can handle the size of string that will
     *  be returned for decrypted data.
     ******/
    if (maxDecryptedStringSize > 0)
    {
        /*
         * If we are going to need more memory than the caller wants to use for
         *  the decrypted string, spit out an error and return false (since
         *  we cannot decrypt the string to the callers limitations).
         ******/
        if (tempOutputLength > maxDecryptedStringSize)
        {
            LOGERROR(
             "Cannot decrypt data, decrypted Size [%d] is going to be too big!",
             tempOutputLength);
            essCrypto_freePassPhrase(tempPassPhrase);
            LOGLIBRETURN(__FUNCTION__);
            return(FALSE);
        }
    }

    /* malloc memory for the decrypted string */
    *decryptedString = malloc(tempOutputLength);

    /*
     * Make sure we successfully malloced memory for the decryptedString string
     ******/
    if (*decryptedString == NULL)
    {
        LOGERROR("Unable to malloc memory for decryption");
        essCrypto_freePassPhrase(tempPassPhrase);
        LOGLIBRETURN(__FUNCTION__);
        return (FALSE);
    }

    /* clean out the memory for the returned string */
    memset(*decryptedString, 0, tempOutputLength);

    /*
     * Loop around decrypting the string with the buffer allocated for
     *  decryption till we cannot fill up the buffer with data anymore.
     ******/
    for (i = 0; i < sizeOfStrToDecrypt/ ESS_CRYPTO_CRYPT_BUFFER_SIZE; i++)
    {
        /* decrypt the contents of the buffer */
        EVP_DecryptUpdate(&openSSLDecryptionStructure,
                         &((*decryptedString)[tmpOutputBufferPosition]),
                         &tmpOffset,
                         &toDecrypt[tmpOutputBufferPosition],
                         ESS_CRYPTO_CRYPT_BUFFER_SIZE);

        /* Increment the position we are at in decrypting the string */
        tmpOutputBufferPosition = tmpOutputBufferPosition + tmpOffset;
    }

    /*
     * if there is data left to decrypt that did not fit exactly within
     *  the buffer, decrypt that remaining bit.
     ******/
    if ( sizeOfStrToDecrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE)
    {
        /* decrypt the contents of the buffer */
         EVP_DecryptUpdate(&openSSLDecryptionStructure,
                         &((*decryptedString)[tmpOutputBufferPosition]),
                         &tmpOffset,
                         &toDecrypt[tmpOutputBufferPosition],
                         sizeOfStrToDecrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE);

        /* Increment the position we are at in decrypting the string */
        tmpOutputBufferPosition = tmpOutputBufferPosition + tmpOffset;

    }

    /* finalize the results from decryption (check CRC) */
    EVP_DecryptFinal(&openSSLDecryptionStructure,
                    &((*decryptedString)[tmpOutputBufferPosition]),
                    &tmpOffset);

   /* set the final length of the decrypted string */
   *sizeOfDecryptedString = tmpOutputBufferPosition + tmpOffset;

   /* see what the length is according to strlen */
   currentDecryptedStrLength = strlen(*decryptedString);
   LOGFORCE("lenght of decrypted string is %d", currentDecryptedStrLength); //xq


   /*
    * If we have the room in memory, NULL terminate the string (just in case
    *  it has not already been done).  Even thought we null out the entire
    *  string when memory was malloc'ed for it.
    ******/
   if (*sizeOfDecryptedString < tempOutputLength)
   {
       (*decryptedString)[*sizeOfDecryptedString] = (char) 0;
   }

   /*
    * If the OpenSSL length (sizeOfDecryptedString is less than the determined
    *  strlen, it means OpenSSL didn't clean up after itself and it left the
    *  encryption "salt" in the string.  If this is the case, remove the
    *  salt from memory (since it could contain sensitive information).
    ******/
   if (*sizeOfDecryptedString < currentDecryptedStrLength)
   {
       LOGDEBUG("Cleaning up Salt in Decrypted String");

       /*
        * loop around and null out each "salt" character in the string
        ******/
       for (i = *sizeOfDecryptedString; i < currentDecryptedStrLength; i++)
       {
           (*decryptedString)[i] = (char) 0;
       }
   }

    LOGREALLYSECURE("Decrypted String is [%s]", *decryptedString);

    essCrypto_freePassPhrase(tempPassPhrase);
    LOGLIBRETURN(__FUNCTION__);
    return (TRUE);
}
============================================================
Here, the decrypted byte array is re-arranged into a character string 
representing the decrypted string. As far as I can see, EVP_DecryptInit(), 
EVP_DecryptUpdate(), and EVP_DecryptFinal() are all library functions in 
OpenSSL (in crypto library?).


The code to encrypt is:
============================================================
bool_t esscrypto_encryptString(unsigned char *toEncrypt,
                               unsigned char *passPhrase,
                               int sizeOfStrToEncrypt,
                               int maxEncryptedStringSize,
                               int *sizeofEncryptedString,
                               unsigned char **encryptedString)
{
    EVP_CIPHER_CTX openSSLEncryptionStructure;
    int tempOutputLength = 0;
    int i = 0;
    int tmpOutputBufferPosition = 0;
    int tmpOffset = 0;
    char *tempPassPhrase = NULL;
    char *tempStrPtr = NULL;

    LOGLIBENTER(__FUNCTION__);

    LOGFORCE("Encrypting [%s] ", toEncrypt);

    /* initialize return values */
    *sizeofEncryptedString = 0;
    *encryptedString = NULL;

    /*
     * Paranoia, if we get "really" big strings to encrypt, we should reject
     *  them in favor of a buffered string encryption method (like what is
     *  done for files).  So spit out a warning and return false.
     ******/
    if ( sizeOfStrToEncrypt > ESS_CRYPTO_MAX_TO_ENCRYPT_STR_SIZE )
    {
        LOGWARN("Encrypting string of size [%d] is too big to encrypt",
                                                         sizeOfStrToEncrypt);
        LOGLIBRETURN(__FUNCTION__);
        return (FALSE);
    }

    /* format the password to be OpenSSL friendly */
    tempPassPhrase = essCrypto_setupPassPhrase(passPhrase);

    /*
     * If we have a null password, something is not right, spit out a warning
     *  and return false.
     ******/
    if (tempPassPhrase == NULL)
    {
        LOGWARN("PassPhrase is NULL");
        LOGLIBRETURN(__FUNCTION__);
        return(FALSE);
    }

    /* Initialize OpenSSL for DES encryption */

    EVP_EncryptInit(&openSSLEncryptionStructure, EVP_des_cbc(), tempPassPhrase,
                          (char *)NULL);

    /****
    * Since we are using DES, we don't need to set the key length always
       set to 64 bits, but if we use other ciphers, we need to do the following:
       EVP_CIPHER_CTX_set_key_length(&openSSLEncryptionStructure, <size>);
       // re-init
       EVP_EncryptInit(&openSSLEncryptionStructure, NULL, passPhrase,
                          (char *)NULL);
    ****/


    /* Get potential size of the output data with a null terminator*/
    tempOutputLength = sizeOfStrToEncrypt +
                     EVP_CIPHER_CTX_block_size(&openSSLEncryptionStructure) + 1;

    /*
     * If the caller put in a non-negative or zero value for the max encrypted
     *  size, then the caller cares about how big of a string will be returned
     *  to it. So check to make sure it can handle the size of string that will
     *  be returned for encrypted data.
     ******/
    if (maxEncryptedStringSize > 0)
    {
        /*
         * If we are going to need more memory than the caller wants to use for
         *  the encrypted string, spit out an error and return false (since
         *  we cannot encrypt the string to the callers limitations).
         ******/
        if (tempOutputLength > maxEncryptedStringSize)
        {
            LOGERROR(
                "Cannot Encrypt data, Encrypted Size is going to be too big!");
            essCrypto_freePassPhrase(tempPassPhrase);
            LOGLIBRETURN(__FUNCTION__);
            return(FALSE);
        }
    }

    /* malloc memory for the encrypted string */
    *encryptedString = malloc(tempOutputLength);

    /*
     * Make sure we successfully malloced memory for the encrypted string
     ******/
    if (*encryptedString == NULL)
    {
        LOGERROR("Unable to malloc memory for encryption");
        LOGLIBRETURN(__FUNCTION__);
        essCrypto_freePassPhrase(tempPassPhrase);
        return (FALSE);
    }

    /* clean out the memory for the returned string */
    memset(*encryptedString, 0, tempOutputLength);

    /*
     * Loop around encrypting the string with the buffer allocated for
     *  encryption till we cannot fill up the buffer with data anymore.
     ******/
    for (i = 0; i < sizeOfStrToEncrypt/ ESS_CRYPTO_CRYPT_BUFFER_SIZE; i++)
    {
        /* encrypt the buffer contents) */
        EVP_EncryptUpdate(&openSSLEncryptionStructure,
                         &((*encryptedString)[tmpOutputBufferPosition]),
                         &tmpOffset,
                         &toEncrypt[tmpOutputBufferPosition],
                         ESS_CRYPTO_CRYPT_BUFFER_SIZE);

        /* Increment the position we are at in encrypting the string */
        tmpOutputBufferPosition = tmpOutputBufferPosition + tmpOffset;
    }

    /*
     * if there is data left to encrypt that did not fit exactly within
     *  the buffer, encrypt that remaining bit.
     ******/
    if ( sizeOfStrToEncrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE)
    {
        /* encrypt the buffer contents) */
        EVP_EncryptUpdate(&openSSLEncryptionStructure,
                          &((*encryptedString)[tmpOutputBufferPosition]),
                         &tmpOffset,
                         &toEncrypt[tmpOutputBufferPosition],
                         sizeOfStrToEncrypt % ESS_CRYPTO_CRYPT_BUFFER_SIZE);

        /* Increment the position we are at in encrypting the string */
        tmpOutputBufferPosition = tmpOutputBufferPosition + tmpOffset;

    }

    /* Finalize the encryption results (generate CRC for example) */
    EVP_EncryptFinal(&openSSLEncryptionStructure,
                     &((*encryptedString)[tmpOutputBufferPosition]),
                     &tmpOffset);

   /* set the total size of the string encrypted */
   *sizeofEncryptedString = tmpOutputBufferPosition + tmpOffset;

    tempStrPtr = ess_crypto_get_hex_string_from_string(*encryptedString);

    if (tempStrPtr != NULL)
    {
        LOGFORCE("Encrypted String (in HEX) is [%s]", tempStrPtr);
        free(tempStrPtr);
    }
    essCrypto_freePassPhrase(tempPassPhrase);

    LOGLIBRETURN(__FUNCTION__);
    return (TRUE);
}
============================================================
I am not sure whether some algorithm in these functions would go awry when 
dealing with the password "$elkins02".

Thanks,
Xu Qiang
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to