Friday, May 2, 2014

Decimal for QT C++

We all know not to use primitive data type double for any arithmetic calculation involves financial or sensitive data which  rounding errors is not acceptable. In that case, Java has java.math.BigDecimal, C# can use System.Decimal, but there is no Decimal built in support for C++.
However there are a few third party libraries to the rescue.
  1. GNU Multiple Precision Arithmetic Library.
  2. qdecimal
  3. Intel's floating point math library
We are going to focus on qdecimal, which specifically target QT C++ at this post.
Because I use Mingw-32 QT version, the library I download does not compile properly, so instead I include the source code into my project.


#include <QCoreApplication>
#include <QtConcurrent/QtConcurrent>
#include "qdecimal/QDecDouble.hh"
#include "qdecimal/QDecNumber.hh"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QDecDouble decDouble = 10.00;
    QDecDouble result = decDouble / 90;
    QTextStream(stdout) << result.toString();
    return a.exec();
}


that's it, hop it helps.

Sunday, April 27, 2014

QT Static Library

It is convenient to have a static library linked to your QT application, not only shrinks down the total deliverable size, but also makes the deploy easier. QT official forum recently published a post on how to compile the library, and here is my experience on executing it under Windows 7.

Things you need.

  1. QT Source Code
  2. 7-zip
  3. QT-mingw-32 version, download it here
  4. Direct X SDK
  5. Windows Power Shell, if you don't already have it.
  6. Power Shell Build Script

Steps to build the library

  1. Install QT-Mingw first, assume it is installed at c:\tools\QT
  2. Install 7 zip
  3. Install Direct X SDK, 
  4. Install Power Shell.
  5. Place qt-everywhere-opensource-src-5.2.x.x.7z under c:\tools
  6. Place the power shell script under c:\tools
  7. Edit the build script as follows.

[CmdletBinding()]
param(
    $QtSrcUrl = "C:/tools/qt-everywhere-opensource-src-5.2.1.7z",
    $QtStaticDir = "C:\tools\Qt\Static",
    $QtVersion = "",
    $MingwDir = "C:\tools\Qt\Qt5.2.1\Tools\mingw48_32",
    [switch]$NoPause = $false
)

Lastly, run power shell script, by opening up a power shell window, and type c:\tools\windows-build-qt-static.ps1

The compilation will take a while (about two hours for my Intel I5 machine), and stay tune for part two for static library linking.

Hope it helps.

Thursday, April 24, 2014

Qt::Concurrent, Multi-Thread under QT programming

Concurrency was always pain in the ass for my short programming career, however under QT C++, there is a easy trick to complete this. It never been this easy, hence I want to share it.
QTConcurrent is what you need, and here is a short example.




#include <QCoreApplication>
#include <QtConcurrent/QtConcurrent>

int plusFunction(int number);

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    int number = 0;
    QFuture<int> future = QtConcurrent::run(plusFunction, number);
    QTextStream(stdout) << future.result() << endl;
    return a.exec();
}


int plusFunction(int number) {
    return number + 1;
}

Wednesday, April 23, 2014

Use AS3Crypto for DES Encryption/Decryption under Flash

As3crypto is a library for encryption under action script 3 (Flash).  However I had major problems implemented it, until I found this post. Here is the code I use with little modification, simple includes this file in your action script to encyrpt/decrypt data.


/*Modify by Kevin Chiang 2014/4/22*/


package
{
    import com.hurlant.crypto.Crypto;
    import com.hurlant.crypto.prng.Random;
    import com.hurlant.crypto.symmetric.ICipher;
    import com.hurlant.crypto.symmetric.IPad;
    import com.hurlant.crypto.symmetric.IVMode;
    import com.hurlant.crypto.symmetric.PKCS5;
    import com.hurlant.util.Base64;
    import com.hurlant.util.Hex;
    import flash.utils.ByteArray;
    
    public class Des
    {
        public static const DEFAULT_CIPHER_NAME:String = "des-cbc";
        public static const DEFAULT_PADNAME:String = "pkcs5";
        public static const NULL_PADDING:String = "null";
        
        private static const RAND:Random = new Random();
        
        private var _name:String;
        private var _key:ByteArray;
        private var _iv:ByteArray;
        private var _padName:String;
        private var _enc:ICipher;
        private var _dec:ICipher;
        
        public function Des(key:ByteArray, iv:ByteArray = null, name:String = DEFAULT_CIPHER_NAME, padName:String = DEFAULT_PADNAME)
        {
            _name = name;
            _key = key;
            _iv = iv;
            _padName = padName;
            init();
        }
        
        private function init():void
        {
            var _pad:IPad = Crypto.getPad(_padName);
            _enc = Crypto.getCipher(_name, _key, _pad);
            _dec = Crypto.getCipher(_name, _key, _pad);
            if (iv)
            {
                if (_enc is IVMode)
                {
                    var encIvm:IVMode = _enc as IVMode;
                    encIvm.IV = iv;
                }
                if (_dec is IVMode)
                {
                    var decIvm:IVMode = _dec as IVMode;
                    decIvm.IV = iv;
                }
            }
        }
        
        public static function generateKey(name:String):ByteArray
        {
            var keyLength:uint = Crypto.getKeySize(name);
            var key:ByteArray = new ByteArray();
            RAND.nextBytes(key, keyLength);
            return key;
        }
        
        public static function generateIV(name:String, key:ByteArray):ByteArray
        {
            var cipher:ICipher = Crypto.getCipher(name, key);
            var iv:ByteArray = new ByteArray();
            RAND.nextBytes(iv, cipher.getBlockSize());
            return iv;
        }
        
        public function encrypt(input:ByteArray):ByteArray
        {
            var src:ByteArray = new ByteArray();
            var result:ByteArray = new ByteArray();
            src.writeBytes(input, 0, input.length);
            
            _enc.encrypt(input);
            result.writeBytes(input, 0, input.length);
            input.length = 0;
            input.writeBytes(src, 0, src.length);
            
            src.clear();
            return result;
        }
        
        public function decrypt(input:ByteArray):ByteArray
        {
            var src:ByteArray = new ByteArray();
            var result:ByteArray = new ByteArray();
            src.writeBytes(input, 0, input.length);
            
            _dec.decrypt(input);
            result.writeBytes(input, 0, input.length);
            input.length = 0;
            input.writeBytes(src, 0, src.length);
            
            src.clear();
            return result;
        }
        
        public function encryptString(input:String):ByteArray
        {
            if (!input || !input.length)
            {
                return null;
            }
            var inputBytes:ByteArray = new ByteArray();
            inputBytes.writeUTFBytes(input);
            return encrypt(inputBytes);
        }
        
        public function encryptString2Hex(input:String):String
        {
            var result:ByteArray = encryptString(input);
            return Hex.fromArray(result);
        }
        
        public function encryptString2Base64(input:String):String
        {
            var result:ByteArray = encryptString(input);
            return Base64.encodeByteArray(result);
        }
        
        public function decryptString(input:String):ByteArray
        {
            if (!input || !input.length)
            {
                return null;
            }
            var inputBytes:ByteArray = new ByteArray();
            inputBytes.writeUTFBytes(input);
            return decrypt(inputBytes);
        }
        
        public function decryptString2Hex(input:String):String
        {
            var result:ByteArray = decryptString(input);
            return Hex.fromArray(result);
        }
        
        public function decryptString2Base64(input:String):String
        {
            var result:ByteArray = decryptString(input);
            return Base64.encodeByteArray(result);
        }
        
        public function set iv(value:ByteArray):void
        {
            _iv = value;
        }
        
        public function get iv():ByteArray
        {
            return _iv;
        }
    }
}

Here is how to use it




        
        private var des:Des;
        private var key:ByteArray;
        private var iv:ByteArray;
        
        private var text:ByteArray;
        
        
        public function Main():void {
            if (stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
                    
            key = Hex.toArray("YOU KEY");
            iv = Hex.toArray("YOUR IV USUALLY 16 digits of HexDecimal");
            des = new Des(key, iv);
            
            var encString:ByteArray = des.encryptString("ABCDEFG"); 
            var b64String:String = Base64.encode(encString.toString());
            trace("Encrypted String = " + b64String);
            
            
            
            var byteArray:ByteArray = Base64.decodeToByteArray(b64String);
            trace(des.decrypt(byteArray).toString());
            


that's it, hope it helps.


Sunday, April 20, 2014

Bcrypt under C/C++ with Botan and password hashing

Recently I have came across the need of a simple encryption mechanism for C++, and after a few trial and error, I decided to use Botan. However under windows 7, compiling it was not as straight forward as in other environments due to lack of built in "make", or other standard commands. With the programming environment I am under (mingw-32), there are few things worth noting.

Here is the official procedure to build it, however there are something missing under windows with mingw-32 environment.

  1. You need python for the Botan configuration script. 
  2. You need mingw32-make.
  3. You need MSYG.
  4. Download Botan.

Make sure you set the environment path for the bin directory of each above mentioned tools, then open a command window run.


python configure.py --cpu=i686 --cc=gcc

that will configure the make file for the build environment.

Then run


mingw32-make

that's it.