aesGladman: fcrypt_encrypt & fcrypt_decrypt

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Arclamp
Posts: 71
Joined: Thu Oct 10, 2013 7:45 pm

aesGladman: fcrypt_encrypt & fcrypt_decrypt

Post by Arclamp »

For the encryption functions, all seems to work if the message length is less than 148 characters, over that and it gets truncated... Any solutions or more?

For the demo issue see function: test_encrypt()

* The sha2 functions appear to work.

Code: Select all

 
#include <irrlicht.h>
//#include "driverChoice.h"
 
#include <iostream>
#include <sstream>          //  u2hex
#include <iomanip>          //  u2hex
//using namespace std;
 
using namespace irr;
 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
 
 
#include "../../source/Irrlicht/aesGladman/aes.h"
 
#include "../../source/Irrlicht/aesGladman/hmac.h"
#include "../../source/Irrlicht/aesGladman/sha1.h"
#include "../../source/Irrlicht/aesGladman/pwd2key.h"
#include "../../source/Irrlicht/aesGladman/fileenc.h"
//#include "../../source/Irrlicht/aesGladman/aesopt.h"
#include "../../source/Irrlicht/aesGladman/prng.h"
#include "../../source/Irrlicht/aesGladman/sha2.h"
//#include "../../source/Irrlicht/aesGladman/aes_modes.h"
 
 
 
IrrlichtDevice* device;
 
 
irr::core::stringc sha2_str(irr::core::stringc &content);
int sha2_file(path fn, stringc &content);
 
 
stringc hex_to_string(const std::string& in);
stringc string_to_hex(const std::string& in);
std::string u2hex(unsigned char c);
stringc exe_cmd(stringc s, int &iret);
 
 
 
 
 
 
s32 str_encrypt(stringc &msg, stringc pass)
{
    /*
    The return value is 0 if the initialization was successful; non-zero values indicate errors. Note that 
    passwords are null-terminated ANSI strings; embedded nulls must not be used. (To avoid incompatibilities 
    between the various character sets in use, especially in different versions of Windows, users should be 
    encouraged to use passwords containing only the "standard" characters in the range 32-127.)
    
    The function returns the password verification value in achPswdVerifier, which must be a 2-byte buffer. 
    If you are encrypting, store this value in the Zip file as indicated by the encryption specification. If 
    you are decrypting, compare this returned value to the value stored in the Zip file. If they are different, 
    then either the password provided by your user was incorrect or the encrypted file has been altered in 
    some way since it was encrypted. (Note that if they match, there is still a 1 in 65,536 chance that an 
    incorrect password was provided.) 
    
    
    
    https://github.com/nih-at/libzip/blob/master/docs/aes_coding_tips.txt
    
    You may need to call the encrypt or decrypt function multiple times,
    passing in successive chunks of data in the buffer. For AE-1 and AE-2
    compatibility, the buffer size must be a multiple of 16 bytes except for
    the last buffer, which may be smaller. For efficiency, a larger buffer size
    such as 32,768 would generally be used.
 
    */
    
    //  ENC TEST:   encode
    u8 salt[16]={0};
    //u8 *salt=prng();
    unsigned char pwVerificationFile[2];
std::cout << "<<< str_encrypt()     0" << std::endl;
    fcrypt_ctx zctx;     // the encryption context
    int rc = fcrypt_init(
                            0x03,       // extra data value indicating key size             (e.header.Sig & 0x00ff0000) >>16,   ?? 1,2,3 ???
                            (const unsigned char*)pass.c_str(),     // the password
                            pass.size(), // number of bytes in password
                            salt,       // the salt
                            (unsigned char*)pwVerificationFile,   // on return contains password verifier
                            &zctx);       // encryption context
    if(rc != 0)
    {
        //  ERROR
        std::cout << "<<< str_encrypt()     rc init error!!!" << std::endl;
        return 1;
    }
    /*
int fcrypt_init(
                            int mode,                               // the mode to be used (input)              ? keysize 
                            const unsigned char pwd[],              // the user specified password (input) 
                            unsigned int pwd_len,                   // the length of the password (input)  
                            const unsigned char salt[],             // the salt (input)                    
                        #ifdef PASSWORD_VERIFIER
                            unsigned char pwd_ver[PWD_VER_LENGTH],  // 2 byte password verifier (output)   
                        #endif
                            fcrypt_ctx      cx[1]);                 // the file encryption context (output)
    */
    
    //fcrypt_encrypt((unsigned char*)msg_enc, strlen(msg_enc), &zctx);
    
    stringc msg_in = msg;   //  copy msg buffer
    msg = "";               //  clear msg buffer for return fill
    stringc buf;
    s32 len = 512;
    u32 i = 0;
    while(i < msg_in.size())
    {
        buf = msg_in.subString(i, len);
        std::cout << "  >--" << buf.c_str() << "--<" << std::endl;
        i += len;
        
        //fcrypt_encrypt((unsigned char*)msg_enc, strlen(msg_enc), &zctx);
        fcrypt_encrypt((unsigned char*)buf.c_str(), strlen(buf.c_str()), &zctx);
        
        msg += buf;
    }
    
    char resMAC[10];
    rc = fcrypt_end(
                        (unsigned char*)resMAC, // on return contains the authentication code
                        &zctx); // encryption context
    if(rc != 10)
    {
        //  ERROR
        std::cout << "<<< <<< <<< ENCRYPTED: Error on encryption closing: " << rc << std::endl;
        return 1;
    }
    return 0;
}
 
 
stringc str_decrypt(stringc msg, stringc pass)
{
    //  ENC TEST: decode
    
    u8 salt[16]={0};
    unsigned char pwVerificationFile[2];
    
    fcrypt_ctx zctx2;     // the encryption context
    int rc = fcrypt_init(
                            0x03,       // extra data value indicating key size             (e.header.Sig & 0x00ff0000) >>16,
                            (const unsigned char*)pass.c_str(),     // the password
                            pass.size(), // number of bytes in password
                            salt,       // the salt
                            (unsigned char*)pwVerificationFile,   // on return contains password verifier
                            &zctx2);       // encryption context
    
    //std::cout << "<<< <<< <<< DECRYPT rc: " << rc << std::endl;       //  0
    if(rc != 0)
    {
        //  ERROR
    }
    /*
int fcrypt_init(
                            int mode,                               // the mode to be used (input)              ? keysize 
                            const unsigned char pwd[],              // the user specified password (input) 
                            unsigned int pwd_len,                   // the length of the password (input)  
                            const unsigned char salt[],             // the salt (input)                    
                        #ifdef PASSWORD_VERIFIER
                            unsigned char pwd_ver[PWD_VER_LENGTH],  // 2 byte password verifier (output)   
                        #endif
                            fcrypt_ctx      cx[1]);                 // the file encryption context (output)
    */
    
    //fcrypt_decrypt((unsigned char*)msg_enc, strlen(msg_enc), &zctx2);
    
    stringc msg_enc = "";
    
    //stringc msg = "Now is the time for all good men to come to the aide of their country.";
    stringc msg_in = msg.c_str();
    stringc buf;
    s32 len = 512;
    u32 i = 0;
    while(i < msg_in.size())
    {
        buf = msg_in.subString(i, len);
        //std::cout << "    >--" << buf.c_str() << "--<" << std::endl;
        i += len;
        
        //fcrypt_encrypt((unsigned char*)msg_enc, strlen(msg_enc), &zctx);
        fcrypt_decrypt((unsigned char*)buf.c_str(), strlen(buf.c_str()), &zctx2);
        
        msg_enc += buf;
    }
    
    
    char resMAC[10];
    rc = fcrypt_end(
                        (unsigned char*)resMAC, // on return contains the authentication code
                        &zctx2); // encryption context
    
    //std::cout << "<<< <<< <<< DECRYPT rc: " << rc << std::endl;       //  10
    if (rc != 10)
    {
        std::cout << "<<< <<< <<< DECRYPTED: Error on decryption closing: " << rc << std::endl;
        //os::Printer::log("Error on encryption closing");
        //delete [] decryptedBuf;
        //return 0;
    }
    
    return msg_enc.c_str();
}
 
 
 
void test_encrypt()
{
    //  ENCRYPT TESTS
    //  =========================================================================
    
    stringc msg = "My message to say... blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! blah blah blah blah blah boing! BOING BOING!!!";
    //stringc msg = "My message to say...wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwjjjttttttttttttttttttttttttttttttttttttttttttttssyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyeey_148";
    std::cout << "<<< <<< <<< LEN: " << msg.size()<< std::endl;
    
    stringc pass = "password";
    
    //  ENCRYPT
    //stringc s_enc = 
    if(str_encrypt(msg, pass))
    {
        //  ERROR
    }
    stringc s_enc = msg;
    std::cout << "<<< <<< <<< ENCRYPTED: " << std::endl;
    //std::cout << "<<< <<< <<< ENCRYPTED: " << s_enc.c_str() << std::endl;
    
    //  CONVERT TO HEX
    stringc s_enc_h = string_to_hex(s_enc.c_str());     //  const std::string& in);
    std::cout << "<<< <<< <<< ENCRYPTED HEX: " << s_enc_h.c_str() << std::endl;
    
    //  CONVERT FROM HEX
    stringc s_enc_hh = hex_to_string(s_enc_h.c_str());  //  const std::string& in);
    //std::cout << "<<< <<< <<< ENCRYPTED DE-HEX: " << s_enc_hh.c_str() << std::endl;
    
    //  DECRYPT
    stringc s_out = str_decrypt(s_enc_hh, pass);
    std::cout << "<<< <<< <<< DECRYPTED: " << s_out.c_str() << std::endl;
    
}
 
void tester()
{
    
    std::cout << "<<< <<< <<< TESTER: chunkin'" << std::endl;
    
    stringc msg = "Now is the time for all good men to come to the aide of their country.";
    stringc buf;
    s32 len = 4;
    u32 i = 0;
    while(i < msg.size())
    {
        buf = msg.subString(i, len);
        std::cout << "  >--" << buf.c_str() << "--<" << std::endl;
        i += len;
    }
    
}
 
void test_salt()
{
    /*
    std::string salt = prng();
    //u8 *salt = prng();
    std::cout << "<<< <<< <<< PRNG: " << salt << std::endl;
    */
}
 
void test_hash()
{
    
    
    //stringc msg = "";
    //stringc msg = "hello";
    stringc msg = "Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. Now is the time for all good men to come to the aide of their country. ";
    //stringc msg = "The quick brown fox jumped over the lazy dog.";
    
    //stringc stroutput = sha2_str("Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! Blah, blah, blah, blah! ");
    
    //  HASH STRING
    stringc stroutput = sha2_str(msg);
    //std::cout << "SHA2 HELLO: " << stroutput.c_str() << std::endl;
    
    //  SYSTEM TEST FOR COMPARISON
    stringc cmd_prefix = "php test_hash.php \"";
    stringc cmd = cmd_prefix+msg+"\"";
    
    int iret = 0;
    stringc php_res = exe_cmd(cmd, iret);
    
    //  OUTPUT
    std::cout << "SHA2 MSG: " << msg.c_str() << std::endl;
    std::cout << "IRR SHA2: " << stroutput.c_str() << std::endl;
    std::cout << "PHP SHA2: " << php_res.c_str() << std::endl;
    
}
 
 
void test_hash_file()
{
    
    
    path fn = "main.cpp";
    stringc shash = "where the hash will be";
    
    //  HASH FILE
    if(sha2_file(fn, shash))
    {
        //  FAILED
    }
    
    //  SYSTEM TEST FOR COMPARISON
    //stringc cmd_prefix = "php test_hash.php \"";
    stringc cmd_prefix = "sha256sum \"";
    stringc cmd = cmd_prefix+fn+"\"";
    
    int iret = 0;
    stringc sys_res = exe_cmd(cmd, iret);
    
    
    //  OUTPUT
    std::cout << "fn: " << fn.c_str() << std::endl;
    std::cout << "IRR SHA2: " << shash.c_str() << std::endl;
    std::cout << "SYS SHA2: " << sys_res.c_str() << std::endl;
    //std::cout << "PHP SHA2: " << php_res.c_str() << std::endl;
    
}
 
 
int main()
{
    device = createDevice(EDT_NULL);
    if (device == 0)
        return 1; // could not create selected driver.
    
    
    
    //test_hash();
    //test_hash_file();
    test_encrypt();
    //tester();
    
    device->drop();
}
 
 
//  CRYPTO FUNCTIONS
//  ==================================================
 
 
#define SHA2___BUF_SIZE 16384
 
 
int sha2_file(path fn, stringc &content)
{
    /*
    $ sha256sum main.cpp 
792108593a153787d9d7a336694d58aa4bce333d9658b79822dc67f850359b67  main.cpp
    */
    
    FILE            *inf;
    sha256_ctx      ctx[1];
    unsigned char   buf[SHA2___BUF_SIZE], hval[SHA256_DIGEST_SIZE];
    int             i;
    
    //  FILE OPEN (non irr)
    if(!(inf = fopen(fn.c_str(), "rb")))
    {
        printf("\n%s not found\n", fn.c_str());
        return 1;
    }
    
    //  HASH START
    sha256_begin(ctx);
    
    do
    {
        //  READ FILE BUFFER
        i = (int)fread(buf, 1, SHA2___BUF_SIZE, inf);
        if(i)
        {
            //  HASH BUFFER
            sha256_hash(buf, i, ctx);
        }
    }
    while(i);
    
    //  FILE CLOSE
    fclose(inf);
    //  HASH FINISH
    sha256_end(hval, ctx);
    
    //  CONVERT TO HEX
    content = "";
    for(i = 0; i < SHA256_DIGEST_SIZE; ++i)
    {
        //printf("%02x", hval[i]);
        content += u2hex(hval[i]).c_str();
    }
    
    return 0;
}
 
 
irr::core::stringc sha2_str(irr::core::stringc &content)
{
    sha256_ctx      ctx[1];
    //unsigned char buf[SHA2___BUF_SIZE];
    unsigned char   hval[SHA256_DIGEST_SIZE];
    int             i;  //, len;
    
    //  HASH START
    sha256_begin(ctx);
    //  HASH CONTENT
    sha256_hash((unsigned char*)content.c_str(), content.size(), ctx);
    //  HASH FINISH
    sha256_end(hval, ctx);
    
    //  CONVERT TO HEX
    irr::core::stringc stroutput = "";
    for(i = 0; i < SHA256_DIGEST_SIZE; ++i)
    {
        stroutput += u2hex(hval[i]).c_str();
    }
    
    //  RETURN HEX
    return stroutput;
}
 
 
 
 
 
//  HELPER FUNCTIONS
//  ==================================================
 
stringc hex_to_string(const std::string& in)
{
    std::string output = "";
 
    if ((in.length() % 2) != 0) {
        //throw std::runtime_error("String is not valid length ...");
        return output.c_str();
    }
    
    size_t cnt = in.length() / 2;
    
    for (size_t i = 0; cnt > i; ++i) {
        uint32_t s = 0;
        std::stringstream ss;
        ss << std::hex << in.substr(i * 2, 2);
        ss >> s;
 
        output.push_back(static_cast<unsigned char>(s));
    }
    return output.c_str();
}
 
stringc string_to_hex(const std::string& in)
{
    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    for (size_t i = 0; in.length() > i; ++i) {
        ss << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(in[i]));
    }
    return ss.str().c_str(); 
}
 
std::string u2hex(unsigned char c)
{
    std::ostringstream o;
    o << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(c);
    //std::cout << "value: " << o.str() << std::endl;
    return o.str();
}
 
stringc exe_cmd(stringc s, int &iret)
{
    stringc sret = "";
    FILE *in;
    char buff[512];
    
    //  ADD TO ALSO COLLECT ERRORS
    s += " 2>&1";
    
    //if(!(in = popen("ls -sail", "r"))){
    if(!(in = popen(s.c_str(), "r")))
    {
        return sret;    //1;
    }
 
    while(fgets(buff, sizeof(buff), in)!=NULL)
    {
        //cout << buff;
        sret += buff;
    }
    
    iret = pclose(in);
    
    return sret;
}
 

And for the sha test, the php file is:

Code: Select all

 
$msg = "hello";
if($argc > 1){
    $msg = $argv[1];
}
echo hash('sha256', $msg);
 

EDIT:
Oh, I'd like to make this compatible with standard php counterparts, so if you know of a simpler way? I have an example php script I test with OpenSSL for testing if need be...
Cheers
Post Reply