user2631433
user2631433

Reputation: 23

AS3 Air App with HMACSHA512 Encryption

Hi I'm developing an Air App that requires authentication and signing of messages via a http api using the HMACSHA512 Encryption standard.

I've found an AS3 library which looks the goods at https://github.com/rubo/flame but its been prepared for flex and I've had a lot of trouble trying to get it to work under Air/Flash IDE and/or extracting the core functions I need.

It would be fantastic if someone could help me getting the flame library / swc loaded via the flash IDE with workine simple example code for encrypting the message 'hello' something like...

import flame.crypto.HMACSHA512;
var test:HMACSHA512 = new HMACSHA512(ByteArrayUtil.fromHexString('mySecretKey'));
trace('encrypted output = ' + test.encryptString('hello'));

Thanks in advance!

Upvotes: 2

Views: 519

Answers (2)

noopic
noopic

Reputation: 11

Optimized and improved code. I removed from it all does not apply to HMACSHA512

HMACSHA512.as

package com.cryptography
{
    public class HMACSHA512
    {
        private static var SHA512Vector:Vector.<Int64> = getSHA512Vector();

        private static function getSHA512Vector():Vector.<Int64>
        {
            var vector:Vector.<Int64> = new <Int64>[];
            vector.push(new Int64(0x428a2f98, -685199838));
            vector.push(new Int64(0x71374491, 0x23ef65cd));
            vector.push(new Int64(-1245643825, -330482897));
            vector.push(new Int64(-373957723, -2121671748));
            vector.push(new Int64(0x3956c25b, -213338824));
            vector.push(new Int64(0x59f111f1, -1241133031));
            vector.push(new Int64(-1841331548, -1357295717));
            vector.push(new Int64(-1424204075, -630357736));
            vector.push(new Int64(-670586216, -1560083902));
            vector.push(new Int64(0x12835b01, 0x45706fbe));
            vector.push(new Int64(0x243185be, 0x4ee4b28c));
            vector.push(new Int64(0x550c7dc3, -704662302));
            vector.push(new Int64(0x72be5d74, -226784913));
            vector.push(new Int64(-2132889090, 0x3b1696b1));
            vector.push(new Int64(-1680079193, 0x25c71235));
            vector.push(new Int64(-1046744716, -815192428));
            vector.push(new Int64(-459576895, -1628353838));
            vector.push(new Int64(-272742522, 0x384f25e3));
            vector.push(new Int64(0xfc19dc6, -1953704523));
            vector.push(new Int64(0x240ca1cc, 0x77ac9c65));
            vector.push(new Int64(0x2de92c6f, 0x592b0275));
            vector.push(new Int64(0x4a7484aa, 0x6ea6e483));
            vector.push(new Int64(0x5cb0a9dc, -1119749164));
            vector.push(new Int64(0x76f988da, -2096016459));
            vector.push(new Int64(-1740746414, -295247957));
            vector.push(new Int64(-1473132947, 0x2db43210));
            vector.push(new Int64(-1341970488, -1728372417));
            vector.push(new Int64(-1084653625, -1091629340));
            vector.push(new Int64(-958395405, 0x3da88fc2));
            vector.push(new Int64(-710438585, -1828018395));
            vector.push(new Int64(0x6ca6351, -536640913));
            vector.push(new Int64(0x14292967, 0xa0e6e70));
            vector.push(new Int64(0x27b70a85, 0x46d22ffc));
            vector.push(new Int64(0x2e1b2138, 0x5c26c926));
            vector.push(new Int64(0x4d2c6dfc, 0x5ac42aed));
            vector.push(new Int64(0x53380d13, -1651133473));
            vector.push(new Int64(0x650a7354, -1951439906));
            vector.push(new Int64(0x766a0abb, 0x3c77b2a8));
            vector.push(new Int64(-2117940946, 0x47edaee6));
            vector.push(new Int64(-1838011259, 0x1482353b));
            vector.push(new Int64(-1564481375, 0x4cf10364));
            vector.push(new Int64(-1474664885, -1136513023));
            vector.push(new Int64(-1035236496, -789014639));
            vector.push(new Int64(-949202525, 0x654be30));
            vector.push(new Int64(-778901479, -688958952));
            vector.push(new Int64(-694614492, 0x5565a910));
            vector.push(new Int64(-200395387, 0x5771202a));
            vector.push(new Int64(0x106aa070, 0x32bbd1b8));
            vector.push(new Int64(0x19a4c116, -1194143544));
            vector.push(new Int64(0x1e376c08, 0x5141ab53));
            vector.push(new Int64(0x2748774c, -544281703));
            vector.push(new Int64(0x34b0bcb5, -509917016));
            vector.push(new Int64(0x391c0cb3, -976659869));
            vector.push(new Int64(0x4ed8aa4a, -482243893));
            vector.push(new Int64(0x5b9cca4f, 0x7763e373));
            vector.push(new Int64(0x682e6ff3, -692930397));
            vector.push(new Int64(0x748f82ee, 0x5defb2fc));
            vector.push(new Int64(0x78a5636f, 0x43172f60));
            vector.push(new Int64(-2067236844, -1578062990));
            vector.push(new Int64(-1933114872, 0x1a6439ec));
            vector.push(new Int64(-1866530822, 0x23631e28));
            vector.push(new Int64(-1538233109, -561857047));
            vector.push(new Int64(-1090935817, -1295615723));
            vector.push(new Int64(-965641998, -479046869));
            vector.push(new Int64(-903397682, -366583396));
            vector.push(new Int64(-779700025, 0x21c0c207));
            vector.push(new Int64(-354779690, -840897762));
            vector.push(new Int64(-176337025, -294727304));
            vector.push(new Int64(0x6f067aa, 0x72176fba));
            vector.push(new Int64(0xa637dc5, -1563912026));
            vector.push(new Int64(0x113f9804, -1090974290));
            vector.push(new Int64(0x1b710b35, 0x131c471b));
            vector.push(new Int64(0x28db77f5, 0x23047d84));
            vector.push(new Int64(0x32caab7b, 0x40c72493));
            vector.push(new Int64(0x3c9ebe0a, 0x15c9bebc));
            vector.push(new Int64(0x431d67c4, -1676669620));
            vector.push(new Int64(0x4cc5d4be, -885112138));
            vector.push(new Int64(0x597f299c, -60457430));
            vector.push(new Int64(0x5fcb6fab, 0x3ad6faec));
            vector.push(new Int64(0x6c44198c, 0x4a475817));
            return vector;
        }

        private static function getHVector():Vector.<Int64>
        {
            var vector:Vector.<Int64> = new <Int64>[];
            vector.push(new Int64(0x6a09e667, -205731576));
            vector.push(new Int64(-1150833019, -2067093701));
            vector.push(new Int64(0x3c6ef372, -23791573));
            vector.push(new Int64(-1521486534, 0x5f1d36f1));
            vector.push(new Int64(0x510e527f, -1377402159));
            vector.push(new Int64(-1694144372, 0x2b3e6c1f));
            vector.push(new Int64(0x1f83d9ab, -79577749));
            vector.push(new Int64(0x5be0cd19, 0x137e2179));
            return vector;
        }

        public static function calculateHash(key:String, data:String):String
        {
            var bkey:Array = rstr2binb(key);
            if (bkey.length > 32) bkey = binb_sha512(bkey, key.length * 8);
            var ipad:Array = new Array(32);
            var opad:Array = new Array(32);
            for (var i:int = 0; i < 32; i++)
            {
                ipad[i] = bkey[i] ^ 0x36363636;
                opad[i] = bkey[i] ^ 0x5C5C5C5C;
            }
            var hash:Array = binb_sha512(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
            return binb2hex(binb_sha512(opad.concat(hash), 1024 + 512));
        }

        private static function binb2hex(input:Array):String
        {
            var hex_tab:String = "0123456789abcdef";
            var output:String = "";
            for (var i:int = 0; i < input.length * 32; i += 8)
            {
                var schar:int = (input[i >> 5] >>> (24 - i % 32)) & 0xFF;
                output += hex_tab.charAt((schar >>> 4) & 0x0F) + hex_tab.charAt(schar & 0x0F);
            }
            return output;
        }

        private static function rstr2binb(string:String):Array
        {
            var stringLength:int = string.length;
            var vectorLength:int = string.length >> 2;
            var result:Array = new Array(vectorLength);
            var i:int;
            for (i = 0; i < vectorLength; i++)
                result[i] = 0;
            for (i = 0; i < stringLength * 8; i += 8)
                result[i >> 5] |= (string.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
            return result;
        }

        private static function binb_sha512(x:Array, len:int):Array
        {
            var H:Vector.<Int64> = getHVector();

            var T1:Int64 = new Int64(0, 0);
            var T2:Int64 = new Int64(0, 0);
            var a:Int64 = new Int64(0,0);
            var b:Int64 = new Int64(0,0);
            var c:Int64 = new Int64(0,0);
            var d:Int64 = new Int64(0,0);
            var e:Int64 = new Int64(0,0);
            var f:Int64 = new Int64(0,0);
            var g:Int64 = new Int64(0,0);
            var h:Int64 = new Int64(0,0);

            var s0:Int64 = new Int64(0, 0);
            var s1:Int64 = new Int64(0, 0);
            var Ch:Int64 = new Int64(0, 0);
            var Maj:Int64 = new Int64(0, 0);
            var r1:Int64 = new Int64(0, 0);
            var r2:Int64 = new Int64(0, 0);
            var r3:Int64 = new Int64(0, 0);
            var j:int;
            var W:Vector.<Int64> = new Vector.<Int64>(80, true);
            for(var i:int = 0; i < 80; i++)
                W[i] = new Int64(0, 0);

            x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
            x[((len + 128 >> 10)<< 5) + 31] = len;
            for (i = 0; i < x.length; i += 32)
            {
                a.copy(H[0]);
                b.copy(H[1]);
                c.copy(H[2]);
                d.copy(H[3]);
                e.copy(H[4]);
                f.copy(H[5]);
                g.copy(H[6]);
                h.copy(H[7]);
                for (j = 0; j < 16; j++)
                {
                    W[j].h = x[i + 2 * j];
                    W[j].l = x[i + 2 * j + 1];
                }
                for (j = 16; j < 80; j++)
                {
                    r1.rrot(W[j - 2], 19);
                    r2.revrrot(W[j - 2], 29);
                    r3.shr(W[j - 2], 6);
                    s1.l = r1.l ^ r2.l ^ r3.l;
                    s1.h = r1.h ^ r2.h ^ r3.h;
                    r1.rrot(W[j - 15], 1);
                    r2.rrot(W[j - 15], 8);
                    r3.shr(W[j - 15], 7);
                    s0.l = r1.l ^ r2.l ^ r3.l;
                    s0.h = r1.h ^ r2.h ^ r3.h;
                    W[j].add4(s1, W[j - 7], s0, W[j - 16]);
                }
                for (j = 0; j < 80; j++)
                {
                    Ch.l = (e.l & f.l) ^ (~e.l & g.l);
                    Ch.h = (e.h & f.h) ^ (~e.h & g.h);
                    r1.rrot(e, 14);
                    r2.rrot(e, 18);
                    r3.revrrot(e, 9);
                    s1.l = r1.l ^ r2.l ^ r3.l;
                    s1.h = r1.h ^ r2.h ^ r3.h;
                    r1.rrot(a, 28);
                    r2.revrrot(a, 2);
                    r3.revrrot(a, 7);
                    s0.l = r1.l ^ r2.l ^ r3.l;
                    s0.h = r1.h ^ r2.h ^ r3.h;
                    Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
                    Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
                    T1.add5(h, s1, Ch, SHA512Vector[j], W[j]);
                    T2.add(s0, Maj);
                    h.copy(g);
                    g.copy(f);
                    f.copy(e);
                    e.add(d, T1);
                    d.copy(c);
                    c.copy(b);
                    b.copy(a);
                    a.add(T1, T2);
                }
                H[0].add(H[0], a);
                H[1].add(H[1], b);
                H[2].add(H[2], c);
                H[3].add(H[3], d);
                H[4].add(H[4], e);
                H[5].add(H[5], f);
                H[6].add(H[6], g);
                H[7].add(H[7], h);
            }
            var hash:Array = new Array(16);
            for (i = 0; i < 8; i++)
            {
                hash[2 * i] = H[i].h;
                hash[2 * i + 1] = H[i].l;
            }
            return hash;
        }
    }
}

Int64.as

package com.cryptography
{
    public class Int64
    {
        public var h:int;
        public var l:int;

        public function Int64(h:int, l:int):void
        {
            this.h = h;
            this.l = l;
        }

        public function copy(src:Int64):void
        {
            this.h = src.h;
            this.l = src.l;
        }

        public function rrot(x:Int64, shift:int):void
        {
            this.l = (x.l >>> shift) | (x.h << (32 - shift));
            this.h = (x.h >>> shift) | (x.l << (32 - shift));
        }

        public function revrrot(x:Int64, shift:int):void
        {
            this.l = (x.h >>> shift) | (x.l << (32 - shift));
            this.h = (x.l >>> shift) | (x.h << (32 - shift));
        }

        public function shr(x:Int64, shift:int):void
        {
            this.l = (x.l >>> shift) | (x.h << (32 - shift));
            this.h = (x.h >>> shift);
        }

        public function add(x:Int64, y:Int64):void
        {
            var w0:uint = (x.l & 0xffff) + (y.l & 0xffff);
            var w1:uint = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
            var w2:uint = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
            var w3:uint = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
            this.l = (w0 & 0xffff) | (w1 << 16);
            this.h = (w2 & 0xffff) | (w3 << 16);
        }

        public function add4(a:Int64, b:Int64, c:Int64, d:Int64):void
        {
            var w0:uint = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
            var w1:uint = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
            var w2:uint = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
            var w3:uint = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
            this.l = (w0 & 0xffff) | (w1 << 16);
            this.h = (w2 & 0xffff) | (w3 << 16);
        }

        public function add5(a:Int64, b:Int64, c:Int64, d:Int64, e:Int64):void
        {
            var w0:uint = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff);
            var w1:uint = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16);
            var w2:uint = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16);
            var w3:uint = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
            this.l = (w0 & 0xffff) | (w1 << 16);
            this.h = (w2 & 0xffff) | (w3 << 16);
        }
    }
}

Upvotes: 1

ZuzEL
ZuzEL

Reputation: 13645

Since actionscript and javascript based on ECMAScript, you can always(and almost always easily) port something from javascript. For example implementation of encryption algorithm.


But! Someone had this already done. SEE HOW

Upvotes: 1

Related Questions