使用HMAC SHA256和base64编码密钥的Javascript

时间:2013-11-13 03:29:21

标签: javascript hmac sha256

我使用以下函数创建base64 HMAC SHA256哈希

https://gist.github.com/hanih/7443134

function sha256() {
    var sha256;

    sha256 = "undefined" !== typeof exports ? exports : {};
    sha256.hexcase = 0;
    sha256.b64pad = "=";
    var b64pad = "=";
    var hexcase = 0;
    sha256.hex_sha256 = function(a) {
        return sha256.rstr2hex(sha256.rstr_sha256(sha256.str2rstr_utf8(a)));
    };
    sha256.b64_sha256 = function(a) {
        return sha256.rstr_sha256(sha256.str2rstr_utf8(a));
    };
    sha256.any_sha256 = function(a, c) {
        return sha256.rstr2any(sha256.rstr_sha256(sha256.str2rstr_utf8(a)), c);
    };
    sha256.hex_hmac_sha256 = function(a, c) {
        return sha256.rstr2hex(sha256.rstr_hmac_sha256(sha256.str2rstr_utf8(a), sha256.str2rstr_utf8(c)));
    };
    sha256.b64_hmac_sha256 = function(a, c) {
        return sha256.rstr2b64(sha256.rstr_hmac_sha256(sha256.str2rstr_utf8(a), sha256.str2rstr_utf8(c)));
    };
    sha256.b64_hmac_sha256_sha256 = function(a, c) {
        return sha256.rstr2b64(sha256.rstr_hmac_sha256(a, sha256.rstr_sha256(c)));
    };
    sha256.any_hmac_sha256 = function(a, c, b) {
        return sha256.rstr2any(sha256.rstr_hmac_sha256(sha256.str2rstr_utf8(a), sha256.str2rstr_utf8(c)), b);
    };
    sha256.sha256_vm_test = function() {
        return "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" == sha256.hex_sha256("abc").toLowerCase();
    };
    sha256.sha256_vm_test1 = function() {
        return "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592" == sha256.hex_sha256("The quick brown fox jumps over the lazy dog").toLowerCase();
    };
    sha256.rstr_sha256 = function(a) {
        return sha256.binb2rstr(sha256.binb_sha256(sha256.rstr2binb(a), 8 * a.length));
    };
    sha256.rstr_hmac_sha256 = function(a, c) {
        var b = sha256.rstr2binb(a);
        16 < b.length && ( b = sha256.binb_sha256(b, 8 * a.length));
        for (var d = Array(16), e = Array(16), f = 0; 16 > f; f++)
            d[f] = b[f] ^ 909522486, e[f] = b[f] ^ 1549556828;
        b = sha256.binb_sha256(d.concat(sha256.rstr2binb(c)), 512 + 8 * c.length);
        return sha256.binb2rstr(sha256.binb_sha256(e.concat(b), 768));
    };
    sha256.rstr2hex = function(a) {
        try { hexcase;
        } catch(c) {
            hexcase = 0;
        }
        for (var b = hexcase ? "0123456789ABCDEF" : "0123456789abcdef", d = "", e, f = 0; f < a.length; f++)
            e = a.charCodeAt(f), d += b.charAt(e >>> 4 & 15) + b.charAt(e & 15);
        return d;
    };
    sha256.rstr2b64 = function(a) {
        try { b64pad;
        } catch(c) {
            b64pad = "";
        }
        for (var b = "", d = a.length, e = 0; e < d; e += 3)
            for (var f = a.charCodeAt(e) << 16 | (e + 1 < d ? a.charCodeAt(e + 1) << 8 : 0) | (e + 2 < d ? a.charCodeAt(e + 2) : 0), g = 0; 4 > g; g++)
                b = 8 * e + 6 * g > 8 * a.length ? b + b64pad : b + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f >>> 6 * (3 - g) & 63);
        return b;
    };
    sha256.rstr2any = function(a, c) {
        var b = c.length, d = [], e, f, g, h, j = Array(Math.ceil(a.length / 2));
        for ( e = 0; e < j.length; e++)
            j[e] = a.charCodeAt(2 * e) << 8 | a.charCodeAt(2 * e + 1);
        for (; 0 < j.length; ) {
            h = [];
            for ( e = g = 0; e < j.length; e++)
                if ( g = (g << 16) + j[e], f = Math.floor(g / b), g -= f * b, 0 < h.length || 0 < f)
                    h[h.length] = f;
            d[d.length] = g;
            j = h;
        }
        b = "";
        for ( e = d.length - 1; 0 <= e; e--)
            b += c.charAt(d[e]);
        d = Math.ceil(8 * a.length / (Math.log(c.length) / Math.log(2)));
        for ( e = b.length; e < d; e++)
            b = c[0] + b;
        return b;
    };
    sha256.str2rstr_utf8 = function(a) {
        for (var c = "", b = -1, d, e; ++b < a.length; )
            d = a.charCodeAt(b), e = b + 1 < a.length ? a.charCodeAt(b + 1) : 0, 55296 <= d && 56319 >= d && 56320 <= e && 57343 >= e && ( d = 65536 + ((d & 1023) << 10) + (e & 1023), b++), 127 >= d ? c += String.fromCharCode(d) : 2047 >= d ? c += String.fromCharCode(192 | d >>> 6 & 31, 128 | d & 63) : 65535 >= d ? c += String.fromCharCode(224 | d >>> 12 & 15, 128 | d >>> 6 & 63, 128 | d & 63) : 2097151 >= d && (c += String.fromCharCode(240 | d >>> 18 & 7, 128 | d >>> 12 & 63, 128 | d >>> 6 & 63, 128 | d & 63));
        return c;
    };
    sha256.str2rstr_utf16le = function(a) {
        for (var c = "", b = 0; b < a.length; b++)
            c += String.fromCharCode(a.charCodeAt(b) & 255, a.charCodeAt(b) >>> 8 & 255);
        return c;
    };
    str2rstr_utf16be = function(a) {
        for (var c = "", b = 0; b < a.length; b++)
            c += String.fromCharCode(a.charCodeAt(b) >>> 8 & 255, a.charCodeAt(b) & 255);
        return c;
    };
    sha256.rstr2binb = function(a) {
        for (var c = Array(a.length >> 2), b = 0; b < c.length; b++)
            c[b] = 0;
        for ( b = 0; b < 8 * a.length; b += 8)
            c[b >> 5] |= (a.charCodeAt(b / 8) & 255) << 24 - b % 32;
        return c;
    };
    sha256.binb2rstr = function(a) {
        for (var c = "", b = 0; b < 32 * a.length; b += 8)
            c += String.fromCharCode(a[b >> 5] >>> 24 - b % 32 & 255);
        return c;
    };
    sha256.sha256_S = function(a, c) {
        return a >>> c | a << 32 - c;
    };
    sha256.sha256_R = function(a, c) {
        return a >>> c;
    };
    sha256.sha256_Ch = function(a, c, b) {
        return a & c ^ ~a & b;
    };
    sha256.sha256_Maj = function(a, c, b) {
        return a & c ^ a & b ^ c & b;
    };
    sha256.sha256_Sigma0256 = function(a) {
        return sha256.sha256_S(a, 2) ^ sha256.sha256_S(a, 13) ^ sha256.sha256_S(a, 22);
    };
    sha256.sha256_Sigma1256 = function(a) {
        return sha256.sha256_S(a, 6) ^ sha256.sha256_S(a, 11) ^ sha256.sha256_S(a, 25);
    };
    sha256.sha256_Gamma0256 = function(a) {
        return sha256.sha256_S(a, 7) ^ sha256.sha256_S(a, 18) ^ sha256.sha256_R(a, 3);
    };
    sha256.sha256_Gamma1256 = function(a) {
        return sha256.sha256_S(a, 17) ^ sha256.sha256_S(a, 19) ^ sha256.sha256_R(a, 10);
    };
    sha256.sha256_Sigma0512 = function(a) {
        return sha256.sha256_S(a, 28) ^ sha256.sha256_S(a, 34) ^ sha256.sha256_S(a, 39);
    };
    sha256.sha256_Sigma1512 = function(a) {
        return sha256.sha256_S(a, 14) ^ sha256.sha256_S(a, 18) ^ sha256.sha256_S(a, 41);
    };
    sha256.sha256_Gamma0512 = function(a) {
        return sha256.sha256_S(a, 1) ^ sha256.sha256_S(a, 8) ^ sha256.sha256_R(a, 7);
    };
    sha256.sha256_Gamma1512 = function(a) {
        return sha256.sha256_S(a, 19) ^ sha256.sha256_S(a, 61) ^ sha256.sha256_R(a, 6);
    };
    sha256.sha256_K = [1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998];
    sha256.binb_sha256 = function(a, c) {
        var b = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225], d = Array(64), e, f, g, h, j, k, m, o, p, n, l, q;
        a[c >> 5] |= 128 << 24 - c % 32;
        a[(c + 64 >> 9 << 4) + 15] = c;
        for ( p = 0; p < a.length; p += 16) {
            e = b[0];
            f = b[1];
            g = b[2];
            h = b[3];
            j = b[4];
            k = b[5];
            m = b[6];
            o = b[7];
            for ( n = 0; 64 > n; n++)
                d[n] = 16 > n ? a[n + p] : sha256.safe_add(sha256.safe_add(sha256.safe_add(sha256.sha256_Gamma1256(d[n - 2]), d[n - 7]), sha256.sha256_Gamma0256(d[n - 15])), d[n - 16]), l = sha256.safe_add(sha256.safe_add(sha256.safe_add(sha256.safe_add(o, sha256.sha256_Sigma1256(j)), sha256.sha256_Ch(j, k, m)), sha256.sha256_K[n]), d[n]), q = sha256.safe_add(sha256.sha256_Sigma0256(e), sha256.sha256_Maj(e, f, g)), o = m, m = k, k = j, j = sha256.safe_add(h, l), h = g, g = f, f = e, e = sha256.safe_add(l, q);
            b[0] = sha256.safe_add(e, b[0]);
            b[1] = sha256.safe_add(f, b[1]);
            b[2] = sha256.safe_add(g, b[2]);
            b[3] = sha256.safe_add(h, b[3]);
            b[4] = sha256.safe_add(j, b[4]);
            b[5] = sha256.safe_add(k, b[5]);
            b[6] = sha256.safe_add(m, b[6]);
            b[7] = sha256.safe_add(o, b[7]);
        }
        return b;
    };
    sha256.safe_add = function(a, c) {
        var b = (a & 65535) + (c & 65535);
        return (a >> 16) + (c >> 16) + (b >> 16) << 16 | b & 65535;
    };
    return sha256;

}

module.exports = sha256;

它包含一个名为b64_hmac_sha256的函数,可以正常工作。

我使用base 64编码密钥,我使用以下函数解码:

https://gist.github.com/hanih/7443203

function urlDecode(str){
    str=str.replace(new RegExp('\\+','g'),' ');
    return unescape(str);
}
function urlEncode(str){
    str=escape(str);
    str=str.replace(new RegExp('\\+','g'),'%2B');
    return str.replace(new RegExp('%20','g'),'+');
}

var END_OF_INPUT = -1;

var base64Chars = new Array(
    'A','B','C','D','E','F','G','H',
    'I','J','K','L','M','N','O','P',
    'Q','R','S','T','U','V','W','X',
    'Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v',
    'w','x','y','z','0','1','2','3',
    '4','5','6','7','8','9','+','/'
);

var reverseBase64Chars = new Array();
for (var i=0; i < base64Chars.length; i++){
    reverseBase64Chars[base64Chars[i]] = i;
}

var base64Str;
var base64Count;
function setBase64Str(str){
    base64Str = str;
    base64Count = 0;
}
function readBase64(){    
    if (!base64Str) return END_OF_INPUT;
    if (base64Count >= base64Str.length) return END_OF_INPUT;
    var c = base64Str.charCodeAt(base64Count) & 0xff;
    base64Count++;
    return c;
}
function encodeBase64(str){
    setBase64Str(str);
    var result = '';
    var inBuffer = new Array(3);
    var lineCount = 0;
    var done = false;
    while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT){
        inBuffer[1] = readBase64();
        inBuffer[2] = readBase64();
        result += (base64Chars[ inBuffer[0] >> 2 ]);
        if (inBuffer[1] != END_OF_INPUT){
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
            if (inBuffer[2] != END_OF_INPUT){
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
                result += (base64Chars [inBuffer[2] & 0x3F]);
            } else {
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c)]);
                result += ('=');
                done = true;
            }
        } else {
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
            result += ('=');
            result += ('=');
            done = true;
        }
        lineCount += 4;
        if (lineCount >= 76){
            result += ('\n');
            lineCount = 0;
        }
    }
    return result;
}
function readReverseBase64(){   
    if (!base64Str) return END_OF_INPUT;
    while (true){      
        if (base64Count >= base64Str.length) return END_OF_INPUT;
        var nextCharacter = base64Str.charAt(base64Count);
        base64Count++;
        if (reverseBase64Chars[nextCharacter]){
            return reverseBase64Chars[nextCharacter];
        }
        if (nextCharacter == 'A') return 0;
    }
    return END_OF_INPUT;
}

function ntos(n){
    n=n.toString(16);
    if (n.length == 1) n="0"+n;
    n="%"+n;
    return unescape(n);
}

function decodeBase64(str){
    setBase64Str(str);
    var result = "";
    var inBuffer = new Array(4);
    var done = false;
    while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
        && (inBuffer[1] = readReverseBase64()) != END_OF_INPUT){
        inBuffer[2] = readReverseBase64();
        inBuffer[3] = readReverseBase64();
        result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
        if (inBuffer[2] != END_OF_INPUT){
            result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
            if (inBuffer[3] != END_OF_INPUT){
                result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
            } else {
                done = true;
            }
        } else {
            done = true;
        }
    }
    return result;
}

var digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
function toHex(n){
    var result = ''
    var start = true;
    for (var i=32; i>0;){
        i-=4;
        var digit = (n>>i) & 0xf;
        if (!start || digit != 0){
            start = false;
            result += digitArray[digit];
        }
    }
    return (result==''?'0':result);
}

function pad(str, len, pad){
    var result = str;
    for (var i=str.length; i<len; i++){
        result = pad + result;
    }
    return result;
}

function encodeHex(str){
    var result = "";
    for (var i=0; i<str.length; i++){
        result += pad(toHex(str.charCodeAt(i)&0xff),2,'0');
    }
    return result;
}

var hexv = {
  "00":0,"01":1,"02":2,"03":3,"04":4,"05":5,"06":6,"07":7,"08":8,"09":9,"0A":10,"0B":11,"0C":12,"0D":13,"0E":14,"0F":15,
  "10":16,"11":17,"12":18,"13":19,"14":20,"15":21,"16":22,"17":23,"18":24,"19":25,"1A":26,"1B":27,"1C":28,"1D":29,"1E":30,"1F":31,
  "20":32,"21":33,"22":34,"23":35,"24":36,"25":37,"26":38,"27":39,"28":40,"29":41,"2A":42,"2B":43,"2C":44,"2D":45,"2E":46,"2F":47,
  "30":48,"31":49,"32":50,"33":51,"34":52,"35":53,"36":54,"37":55,"38":56,"39":57,"3A":58,"3B":59,"3C":60,"3D":61,"3E":62,"3F":63,
  "40":64,"41":65,"42":66,"43":67,"44":68,"45":69,"46":70,"47":71,"48":72,"49":73,"4A":74,"4B":75,"4C":76,"4D":77,"4E":78,"4F":79,
  "50":80,"51":81,"52":82,"53":83,"54":84,"55":85,"56":86,"57":87,"58":88,"59":89,"5A":90,"5B":91,"5C":92,"5D":93,"5E":94,"5F":95,
  "60":96,"61":97,"62":98,"63":99,"64":100,"65":101,"66":102,"67":103,"68":104,"69":105,"6A":106,"6B":107,"6C":108,"6D":109,"6E":110,"6F":111,
  "70":112,"71":113,"72":114,"73":115,"74":116,"75":117,"76":118,"77":119,"78":120,"79":121,"7A":122,"7B":123,"7C":124,"7D":125,"7E":126,"7F":127,
  "80":128,"81":129,"82":130,"83":131,"84":132,"85":133,"86":134,"87":135,"88":136,"89":137,"8A":138,"8B":139,"8C":140,"8D":141,"8E":142,"8F":143,
  "90":144,"91":145,"92":146,"93":147,"94":148,"95":149,"96":150,"97":151,"98":152,"99":153,"9A":154,"9B":155,"9C":156,"9D":157,"9E":158,"9F":159,
  "A0":160,"A1":161,"A2":162,"A3":163,"A4":164,"A5":165,"A6":166,"A7":167,"A8":168,"A9":169,"AA":170,"AB":171,"AC":172,"AD":173,"AE":174,"AF":175,
  "B0":176,"B1":177,"B2":178,"B3":179,"B4":180,"B5":181,"B6":182,"B7":183,"B8":184,"B9":185,"BA":186,"BB":187,"BC":188,"BD":189,"BE":190,"BF":191,
  "C0":192,"C1":193,"C2":194,"C3":195,"C4":196,"C5":197,"C6":198,"C7":199,"C8":200,"C9":201,"CA":202,"CB":203,"CC":204,"CD":205,"CE":206,"CF":207,
  "D0":208,"D1":209,"D2":210,"D3":211,"D4":212,"D5":213,"D6":214,"D7":215,"D8":216,"D9":217,"DA":218,"DB":219,"DC":220,"DD":221,"DE":222,"DF":223,
  "E0":224,"E1":225,"E2":226,"E3":227,"E4":228,"E5":229,"E6":230,"E7":231,"E8":232,"E9":233,"EA":234,"EB":235,"EC":236,"ED":237,"EE":238,"EF":239,
  "F0":240,"F1":241,"F2":242,"F3":243,"F4":244,"F5":245,"F6":246,"F7":247,"F8":248,"F9":249,"FA":250,"FB":251,"FC":252,"FD":253,"FE":254,"FF":255
};

function decodeHex(str){
    str = str.toUpperCase().replace(new RegExp("s/[^0-9A-Z]//g"));
    var result = "";
    var nextchar = "";
    for (var i=0; i<str.length; i++){
        nextchar += str.charAt(i);
        if (nextchar.length == 2){
            result += ntos(hexv[nextchar]);
            nextchar = "";
        }
    }
    return result;

}

当解码的密钥包含不常见的字符时会出现问题

此编码密钥有效:

dGhpc2lzYWxvbmdlcm1lc3NhZ2VvZmNvdXJzZXRoaXNpc2Fsb25nZXJtZXNzYWdlb2Zjb3Vyc2U=

但这不起作用

5VoyMfmtN7lBiFlyDcMX85Hjvw/oxj8IVcB0dn8N6CXr+F0nuPI2LQ3K/w==

0 个答案:

没有答案