《对基于HTTP协议的密码传输安全的一些思考》相关js代码

首先是 RSA 加密代码:
function Random() {
    
return Math.round(Math.random() * 254+ 1;
}

function ToBase32(value) {
    
var base32 = 'abcdefghijklmnopqrstuvwxyz456789';
    
var length = parseInt(((value.length << 4+ 4/ 5);
    
var result = '';
    
var cur_i = 0;
    
var cur_u = 0;
    
var index;
    
var k;
    
for (var i = 0; i < length; i++) {
        index 
= 0;
        
for (var j = 0; j < 5; j++) {
            k 
= i * 5 + j;
            
if (k == value.length << 4)
                
break;
            
if ((k & 0xf== 0)
                cur_u 
= value[cur_i++];
            index 
<<= 1;
            index 
|= (cur_u & 0x8000== 0 ? 0 : 1;
            cur_u 
<<= 1;
        }
        result 
+= base32.charAt(index);
    }
    
return result;
}

function FromBase32(value) {
    
var base32 = 'abcdefghijklmnopqrstuvwxyz456789';
    
var bl = value.length * 5 >>> 3;
    
var result = new Array(bl + 1 >>> 1);
    
var cur_i = 0;
    
var cur_v = 0;
    
var index = (bl & 1<< 3;
    
var k = 0;
    
while (k < value.length * 5 && (index >>> 4< result.length) {
        
if (k % 5 == 0)
        {
            cur_v 
= base32.indexOf(value.charAt(cur_i++));
            
if (cur_i == value.length && (value.length & 7!= 0)
                cur_v 
<<= value.length * 5 & 7;
        }
        result[index 
>>> 4<<= 1;
        result[index 
>>> 4|= (cur_v & 0x10== 0 ? 0 : 1;
        cur_v 
<<= 1;
        index
++;
        k
++;
    }
    
return result;
}

function Multiply(value1, value2) {
    
var result = new Array(value1.length + value2.length);
    
for (var i = 0; i < value1.length + value2.length; i++)
        result[i] 
= 0;
    
for (var i = value1.length - 1; i >= 0; i--)
    {
        
var inc = 0;
        
for (var j = value2.length - 1; j >= 0; j--)
        {
            
var tmp = value1[i] * value2[j] + result[i + j + 1+ inc;
            result[i 
+ j + 1= tmp & 0xffff;
            inc 
= tmp >>> 0x10;
        }
        result[i] 
= inc;
    }
    
return result;
}

function Modulus(value, modulus) {
    
if (value.length < modulus.length)
        
return value;
    
var h = 0;
    
var result = new Array(modulus.length);
    
var cur = result.length;
    
for (var i = 0; i < result.length; i++)
        result[i] 
= value[i];
    
do
    {
        
var div = parseInt((((h << 0x10| result[0]) >>> 0/ modulus[0]);
        
if (div > 0)
        {
            
var sub = 0;
            
for (var i = result.length - 1; i >= 0; i--)
            {
                
var tmp = div * modulus[i] + sub;
                sub 
= tmp >>> 0x10;
                tmp 
&= 0xffff;
                
if (result[i] >= tmp)
                    result[i] 
-= tmp;
                
else
                {
                    result[i] 
+= 0x10000 - tmp;
                    sub
++;
                }
            }
            
while (h < sub)
            {
                
var add = 0;
                
for (var i = result.length - 1; i >= 0; i--)
                {
                    
var tmp = result[i] + modulus[i] + add;
                    add 
= tmp >>> 0x10;
                    result[i] 
= tmp & 0xffff;
                }
                h 
+= add;
            }
        }
        
if (cur >= value.length)
            
break;
        h 
= result[0];
        
for (var i = 0; i < result.length - 1; i++)
            result[i] 
= result[i + 1];
        result[result.length 
- 1= value[cur++];
    }
    
while (true);
    
return result;
}

function Encrypt(str, keySize, exponent, modulus) {
    
var data = new Array(keySize >>> 4);
    data[
0= 2;
    
var index = 2;
    
for (var i = 2; i < keySize / 8 - str.length - 1; i++) {
        data[index 
>>> 1<<= 8;
        data[index 
>>> 1|= Random() & 0xff;
        index
++;
    }
    data[index 
>>> 1<<= 8;
    index
++;
    
for(var i = 0; i < str.length; i++) {
        data[index 
>>> 1<<= 8;
        data[index 
>>> 1|= str.charCodeAt(i) & 0xff;
        index
++;
    }
    
var result = new Array(1);
    result[
0= 1;
    
for (var i = exponent.length - 1; i >= 0; i--)
        
for (var j = 0; j < 0x10; j++)
        {
            
if (i == 0 && (exponent[i] >>> j) == 0)
                
break;
            
if (((exponent[i] >>> j) & 1!= 0)
                result 
= Modulus(Multiply(result, data), modulus);
            data 
= Modulus(Multiply(data, data), modulus);
        }
    
return ToBase32(result);
}

function RSA(str, keySize, exponent, modulus) {
    
if (typeof(str) != 'string')
        
return '';
    
var max = keySize / 8 - 11;
    
var length = str.length;
    
var index = 0;
    
var result = '';
    
var e = FromBase32(exponent);
    
var m = FromBase32(modulus);
    
while (length > max) {
        result 
+= Encrypt(str.substr(index, max), keySize, e, m);
        length 
-= max;
        index 
+= max;
    }
    result 
+= Encrypt(str.substr(index, length), keySize, e, m);
    
return result;
}

其中:str 为待加密字符串,在这里仅支持 ASCII 字符;keySize 为密钥位数,一般在 .NET 中为 1024 位;exponent 和 modulus 为 RSA 加密密钥。一般使用时可以从服务器获取 keySize, exponent 和 modulus。

然后是 SHA1 哈希代码:

function HashTransform(h, buffer) {
    
var A = h[0], B = h[1], C = h[2], D = h[3], E = h[4];
    
var expand = new Array();
    expand.length 
= 80;
    
for (var i = 0; i < 0x10; i++)
        expand[i] 
= (buffer[i * 4<< 24| (buffer[i * 4 + 1<< 16| (buffer[i * 4 + 2<< 8| buffer[i * 4 + 3];
    
for (var i = 16; i < 80; i++)
    {
        expand[i] 
= expand[i - 3^ expand[i - 8^ expand[i - 14^ expand[i - 16];
        expand[i] 
= (expand[i] << 1| (expand[i] >>> 31);
    }
    
var index = 0;
    
while (index < 20)
    {
        E 
+= ((((A << 5| (A >>> 0x1b)) + (D ^ (B & (C ^ D)))) + expand[index]) + 0x5a827999;
        B 
= (B << 30| (B >>> 2);
        D 
+= ((((E << 5| (E >>> 0x1b)) + (C ^ (A & (B ^ C)))) + expand[index + 1]) + 0x5a827999;
        A 
= (A << 30| (A >>> 2);
        C 
+= ((((D << 5| (D >>> 0x1b)) + (B ^ (E & (A ^ B)))) + expand[index + 2]) + 0x5a827999;
        E 
= (E << 30| (E >>> 2);
        B 
+= ((((C << 5| (C >>> 0x1b)) + (A ^ (D & (E ^ A)))) + expand[index + 3]) + 0x5a827999;
        D 
= (D << 30| (D >>> 2);
        A 
+= ((((B << 5| (B >>> 0x1b)) + (E ^ (C & (D ^ E)))) + expand[index + 4]) + 0x5a827999;
        C 
= (C << 30| (C >>> 2);
        index 
+= 5;
    }
    
while (index < 40)
    {
        E 
+= ((((A << 5| (A >>> 0x1b)) + ((B ^ C) ^ D)) + expand[index]) + 0x6ed9eba1;
        B 
= (B << 30| (B >>> 2);
        D 
+= ((((E << 5| (E >>> 0x1b)) + ((A ^ B) ^ C)) + expand[index + 1]) + 0x6ed9eba1;
        A 
= (A << 30| (A >>> 2);
        C 
+= ((((D << 5| (D >>> 0x1b)) + ((E ^ A) ^ B)) + expand[index + 2]) + 0x6ed9eba1;
        E 
= (E << 30| (E >>> 2);
        B 
+= ((((C << 5| (C >>> 0x1b)) + ((D ^ E) ^ A)) + expand[index + 3]) + 0x6ed9eba1;
        D 
= (D << 30| (D >>> 2);
        A 
+= ((((B << 5| (B >>> 0x1b)) + ((C ^ D) ^ E)) + expand[index + 4]) + 0x6ed9eba1;
        C 
= (C << 30| (C >>> 2);
        index 
+= 5;
    }
    
while (index < 60)
    {
        E 
+= ((((A << 5| (A >>> 0x1b)) + ((B & C) | (D & (B | C)))) + expand[index]) + 0x8f1bbcdc;
        B 
= (B << 30| (B >>> 2);
        D 
+= ((((E << 5| (E >>> 0x1b)) + ((A & B) | (C & (A | B)))) + expand[index + 1]) + 0x8f1bbcdc;
        A 
= (A << 30| (A >>> 2);
        C 
+= ((((D << 5| (D >>> 0x1b)) + ((E & A) | (B & (E | A)))) + expand[index + 2]) + 0x8f1bbcdc;
        E 
= (E << 30| (E >>> 2);
        B 
+= ((((C << 5| (C >>> 0x1b)) + ((D & E) | (A & (D | E)))) + expand[index + 3]) + 0x8f1bbcdc;
        D 
= (D << 30| (D >>> 2);
        A 
+= ((((B << 5| (B >>> 0x1b)) + ((C & D) | (E & (C | D)))) + expand[index + 4]) + 0x8f1bbcdc;
        C 
= (C << 30| (C >>> 2);
        index 
+= 5;
    }
    
while (index < 80)
    {
        E 
+= ((((A << 5| (A >>> 0x1b)) + ((B ^ C) ^ D)) + expand[index]) + 0xca62c1d6;
        B 
= (B << 30| (B >>> 2);
        D 
+= ((((E << 5| (E >>> 0x1b)) + ((A ^ B) ^ C)) + expand[index + 1]) + 0xca62c1d6;
        A 
= (A << 30| (A >>> 2);
        C 
+= ((((D << 5| (D >>> 0x1b)) + ((E ^ A) ^ B)) + expand[index + 2]) + 0xca62c1d6;
        E 
= (E << 30| (E >>> 2);
        B 
+= ((((C << 5| (C >>> 0x1b)) + ((D ^ E) ^ A)) + expand[index + 3]) + 0xca62c1d6;
        D 
= (D << 30| (D >>> 2);
        A 
+= ((((B << 5| (B >>> 0x1b)) + ((C ^ D) ^ E)) + expand[index + 4]) + 0xca62c1d6;
        C 
= (C << 30| (C >>> 2);
        index 
+= 5;
    }
    h[
0+= A;
    h[
1+= B;
    h[
2+= C;
    h[
3+= D;
    h[
4+= E;
}

function HashData(h, value, buffer, offset) {
    
var length = value.length;
    
var srcOffset = 0;
    
var dstOffset = offset & 0x3f;
    
var count = offset + length;
    
if (dstOffset > 0 && (dstOffset + length) >= 0x40) {
        
var x = srcOffset, y = dstOffset;
        
for (var i = 0; i < 0x40 - dstOffset; i++)
            buffer[y
++= value[x++& 0xff;
        srcOffset 
+= 0x40 - dstOffset;
        length 
-= 0x40 - dstOffset;
        HashTransform(h, buffer);
        dstOffset 
= 0;
    }
    
while (length >= 0x40)
    {
        
var x = srcOffset, y = 0;
        
for (var i = 0; i < 0x40; i++)
            buffer[y
++= value[x++& 0xff;
        srcOffset 
+= 0x40;
        length 
-= 0x40;
        HashTransform(h, buffer);
    }
    
if (length > 0) {
        
var x = srcOffset, y = dstOffset;
        
for (var i = 0; i < length; i++)
            buffer[y
++= value[x++& 0xff;
    }
    
return count;
}

function SHA1(str) {
    
if (typeof(str) != 'string')
        
return '';
    
var value = new Array();
    value.length 
= str.length;
    
for (var i = 0; i < value.length; i++)
        value[i] 
= str.charCodeAt(i) & 0xff;
    
var h = new Array(0x674523010xefcdab890x98badcfe0x103254760xc3d2e1f0);
    
var buffer = new Array();
    buffer.length 
= 0x40;
    
var count = HashData(h, value, buffer, 0);
    
var length = 0x40 - (count & 0x3f);
    
if (length <= 8)
        length 
+= 0x40;
    
var block = new Array()
    block.length 
= length;
    block[
0= 0x80;
    
for (var i = 1; i < length - 8; i++)
        block[i] 
= 0;
    
var bit = count << 3;
    
for (var i = 1; i <= 8; i++) {
        block[length 
- i] = bit & 0xff;
        bit 
>>>= 8;
    }
    HashData(h, block, buffer, count);
    
var base32 = 'abcdefghijklmnopqrstuvwxyz456789';
    
var result = '';
    
var cur_i = 0;
    
var cur_u = 0;
    
var index;
    
var k;
    
for (var i = 0; i < 32; i++) {
        index 
= 0;
        
for (var j = 0; j < 5; j++) {
            k 
= i * 5 + j;
            
if (k == 160)
                
break;
            
if (k % 32 == 0)
                cur_u 
= h[cur_i++];
            index 
<<= 1;
            index 
|= (cur_u & 0x80000000== 0 ? 0 : 1;
            cur_u 
<<= 1;
        }
        result 
+= base32.charAt(index);
    }
    
return result;
}

其中:str 为待加密字符串,在这里仅支持 ASCII 字符。

另外,RSA 中的 exponent 和 modulus 以及 RSA 和 SHA1 的返回值均使用伪 Base32 编码,.NET 可参考 http://www.cnblogs.com/hust21941/archive/2008/08/13/base32.html ,其他语言可以自行修改。

posted @ 2008-08-16 18:22  田嵩  阅读(894)  评论(0编辑  收藏  举报