/**
* 태그의 길이 값을 계산하여 반환한다.
*/
getLength: function ()
{
var tag = this.getData () ,
length = tag & 127 ;
if ( length == tag )
return length ;
if ( length === 0 )
return -1 ;
for ( var i = 0 , tag = 0 ; i < length ; i ++ )
tag = ( tag << 8 ) | this.getData () ;
return tag ;
} ,
/**
* 서브 데이터로 생성할 내용이 존재하는지 확인한다.
* @param Integer tag 태그
* @param Integer length 길이
*/
has: function ( tag , length )
{
if ( tag & 32 )
return true ;
if ( tag < 3 || tag > 4 )
return false ;
var p = new Stream ( this ) ;
if ( tag == 3 )
p.getData() ;
var sub = p.getData () ;
if ( ( sub >> 6 ) & 1 )
return false ;
var l = p.getLength () ;
return ( ( p.pos - this.pos ) + l == length ) ;
}
}
/**
* ASN.1 클래스
* @param Array sub 서브 데이터
* @param Stream stream 데이터 스트림
* @param Integer start 시작 위치
* @param Integer end 종료 위치
*/
function ASN1 ( sub , stream , start , end )
{
if ( sub.length != 0 )
this.sub = sub ;
this.stream = stream ;
this.stream.start = start ;
this.stream.end = end ;
}
ASN1.prototype =
{
/**
* Hex 문자열(16진수)로 변환하여 반환한다.
*/
getHex: function ()
{
var end = this.stream.pos + this.stream.start + Math.abs ( this.stream.end ) ,
result = '' , h , i ;
for ( i = this.stream.pos ; i < end ; i ++ )
{
h = this.stream.data ;
result += Convert.decimalToHex ( ( h >> 4 ) & 15 ) + Convert.decimalToHex ( h & 15 ) ;
}
return result.substr ( this.stream.start * 2 , this.stream.end * 2 ) ;
}
}
/**
* ASN.1 규격을 디코딩하여 ASN.1 객체로 반환한다.
* @param Mixed stream 데이터 스트림 혹은 Hex 문자열(ASN.1 규격)
*/
ASN1.decode = function ( stream )
{
var clone = new Stream ( stream ) ,
tag = stream.getData () ,
end = stream.getLength () ,
start = stream.pos - clone.pos ,
sub = [] ;
if ( ! stream.has ( tag , end ) )
stream.pos += end ;
else
{
var temp = stream.pos + end ;
if ( tag == 3 )
stream.getData () ;
while ( stream.pos < temp )
sub.push ( ASN1.decode ( stream ) ) ;
}
return new ASN1 ( sub , clone , start , end ) ;
} ;
/**
* BigInt 클래스
* @param Mixed value 값
* @param Integer base 진수 ( 2제곱만 가능하다. 예) 2, 4, 8, 16, 24 ... 256 )
*/
function BigInt ( value , base )
{
base = 256 ;
this.total = 0 ;
this.start = 0 ;
var unit = ( base >> 1 ).toString( 2 ).length , shift = 0 , t ;
for ( i = value.length - 1 ; i > -1 ; i -- )
{
t = base == 16 ? Convert.hexToDecimal ( value ) : value & 255 ;
if ( shift == 0 )
this[this.total ++] = t ;
else if ( shift + unit > BIT )
{
this[this.total ++] = ( t >> ( BIT - shift ) ) ;
this[this.total - 2] += ( t & ( ( 1 << ( BIT - shift ) ) - 1 ) ) << shift ;
}
else
this[this.total - 1] += t << shift ;
shift += unit ;
if ( shift >= BIT )
shift -= BIT ;
}
this.reset () ;
}
BigInt.prototype =
{
/**
* 현재 값에서 target 을 뺀 후, 결과를 반환한다.
* @param BigInt target 뺄 값
* @return BigInt 남은 값 ( this - target ) ;
* @see 현재 값에 영향을 주지 않는다.
*/
minus: function ( target )
{
var result = new BigInt ,
min = Math.min ( target.total , this.total ) ;
for ( var i = t = 0 ; i < min ; i ++ , t >>= BIT )
result = ( t += this - target ) & BITMASK ;
if ( target.total < this.total )
{
for ( t -= target.start ; i < this.total ; i ++ , t >>= BIT )
result = ( t += this ) & BITMASK ;
t += this.start ;
}
else
{
for ( t += this.start ; i < target.total ; i ++ , t >>= BIT )
result = ( t -= target ) & BITMASK ;
t -= target.start ;
}
if ( t < -1 )
result[i ++] = BITMAX + t ;
else if ( t > 0 )
result[i ++] = t ;
result.reset ( i , t < 0 ? -1 : 0 ) ;
return result ;
} ,
/**
* 데이터 구조를 재 정의하고 정리한다.
* @param Integer total 배열 총 수
* @param Integer start 시작 위치
*/
reset: function ( total , start )
{
if ( total != undefined )
this.total = total ;
if ( start != undefined )
this.start = start ;
if ( this.total <= 0 )
return ;
var start = this.start & BITMASK ;
while ( this[this.total - 1] == start )
this.total -- ;
} ,
/**
* 데이터 구조의 각 배열을 덮어쓴다.
* @param BigInt value 덮어 쓸 값
*/
overwrite: function ( value )
{
for ( var i = 0 ; i < value.total ; i ++ )
this = value ;
this.reset ( value.total , value.start ) ;
} ,
/**
* 데이터 구조의 원소를 move 만큼 좌측(증가)으로 이동하고, 그 결과를 result 에 할당한다.
* @param Integer move 이동 수
* @param BigInt result 결과 값
* @see result 의 기존 데이터를 초기화하지 않는다.
*/
moveLeftTo: function ( move , result )
{
for ( var i = 0 ; i < move ; i ++ )
result = 0 ;
for ( i = 0 ; i < this.total ; i ++ )
result[i + move] = this ;
result.reset ( this.total + move , this.start ) ;
} ,
/**
* 데이터 구조의 원소를 move 만큼 우측(증가)으로 이동하고, 그 결과를 result 에 할당한다.
* @param Integer move 이동 수
* @param BigInt result 결과 값
* @see result 의 기존 데이터를 초기화하지 않는다.
*/
moveRightTo: function ( move , result )
{
for ( var i = move ; i < this.total ; i ++ )
result[i - move] = this ;
result.reset ( this.total > move ? this.total - move : 0 , this.start ) ;
} ,
/**
* 현재 값에 왼쪽으로 비트 시프트 연산을 수행하고, 그 결과를 result 에 할당한다.
* @param Integer shift 이동 수
* @param BigInt result 결과 값
* @see result 의 기존 데이터를 초기화하지 않는다.
*/
shiftLeftTo: function ( shift , result )
{
var pos = Math.floor ( shift / BIT ) ,
split = shift & BIT ,
mod = BIT - split ,
bit = ( 1 << mod ) - 1 ,
remain = ( this.start << split ) & BITMASK ;
for ( var i = this.total - 1 ; i > -1 ; i -- )
{
result[i + pos + 1] = ( this >> mod ) + remain ;
remain = ( this & bit ) << split ;
}
result[pos] = remain ;
for ( i = pos - 1 ; i > -1 ; i -- ) // 자리수 채우기
result = 0 ;
result.reset ( this.total + pos + 1 , this.start ) ;
} ,
/**
* 현재 값에 오른쪽으로 비트 시프트 연산을 수행하고, 그 결과를 result 에 할당한다.
* @param Integer shift 이동 수
* @param BigInt result 결과 값
* @see result 의 기존 데이터를 초기화하지 않는다.
*/
shiftRightTo: function ( shift , result )
{
var pos = Math.floor ( shift / BIT ) ;
if ( pos >= this.total )
return result.total = 0 ;
var split = shift & BIT ,
mod = BIT - split ,
bit = ( 1 << split ) - 1 ;
result[0] = this[pos] >> split ;
for ( var i = pos + 1 ; i < this.total ; i ++ )
{
result[i - pos - 1] += ( this & bit ) << mod ;
result[i - pos] = this >> split ;
}
if ( split > 0 )
result[this.total - pos - 1] += ( this.start & bit ) << mod ;
result.reset ( this.total - pos , this.start ) ;
} ,
/**
* 현재 값을 256진수로 변환하여 배열로 반환한다.
* @return Array 현재 값(256진수)
*/
getByteArray: function ()
{
var block = BIT - ( ( this.total * BIT ) & 7 ) ,
byte , total = this.total ,
result = [] , i = 0 ;
result[0] = this.start ;
if ( total -- > 0 )
{
byte = this[total] >> block ;
if ( block < BIT && byte != ( this.start & BITMASK ) >> block )
result[i ++] = byte | ( this.start << ( BIT - block ) ) ;
while ( total > -1 )
{
if ( block < 8 )
{
byte = ( this[total] & ( ( 1 << block ) - 1 ) ) << ( 8 - block ) ;
byte += this[-- total] >> ( block += BIT - 8 ) ;
}
else
{
byte = ( this[total] >> ( block -= 8 ) ) & HEX['8'] ;
if ( block <= 0 )
block += BIT , total -- ;
}
if ( ( byte & 128 ) != 0 )
byte += -256 ;
if ( i == 0 && ( this.start & 128 ) != ( byte & 128 ) )
i ++ ;
if ( i > 0 || byte != this.start )
result[i ++] = byte ;
}
}
return result ;
} ,
/**
* 멀티 비트를 계산하여 반환한다.
* @param Integer i 현재 객체 순번
* @param Integer value 기준 값
* @param BigInt target 할당 객체
* @param Integer j 할당 객체 순번
* @param Integer result 대체 값
* @param Integer repeat 반복 수
*/
getMultiBit: function ( i , value , target , j , result , repeat )
{
var bit = BIT / 2 ,
mask = value & HEX[bit] ,
quar = value >> bit ;
for ( var l , q , m ; repeat > 0 ; repeat -- )
{
l = this & HEX[bit] ;
q = this[i ++] >> bit ;
m = quar * l + q * mask ;
l = mask * l
+ ( ( m & HEX[bit] ) << bit )
+ target[j]
+ ( BIT == 30 ? result & HEX[BIT] : result ) ;
result = ( l >>> BIT )
+ ( m >>> bit )
+ ( quar * q )
+ ( BIT == 30 ? result >>> BIT : 0 ) ;
target[j ++] = l & HEX[BIT] ;
}
return result ;
} ,
/**
* 현재 값을 인수 n 으로 나눈 나머지 값을 remain 에 할당한다.
* @param BigInt n 나눌 값 ( RSA 암/복호화 공통키 n 임 )
* @param BigInt remain 나머지 값
* @see remain 의 기존 데이터를 초기화하지 않는다.
*/
modTo: function ( n , remain )
{
if ( n.total <= 0 )
return ;
if ( this.total < n.total && remain != null )
return remain.overwrite ( this ) ;
var t = new BigInt ,
bit = BIT - n[n.total - 1].toString ( 2 ).length ;
if ( bit > 0 )
{
n.shiftLeftTo ( bit , t ) ;
this.shiftLeftTo ( bit , remain ) ;
}
else
{
t.overwrite ( n ) ;
remain.overwrite ( this ) ;
}
var total = t.total , last = t[total - 1] ;
if ( last == 0 )
return ;
var key = last * CAL + ( total > 1 ? t[total - 2] >> UNIT : 0 ) ,
j = remain.total ,
i = j - total ,
m = new BigInt ;
t.moveLeftTo ( i , m ) ;
if ( remain.diff ( m ) > -1 )
{
remain[remain.total ++ ] = 1 ;
remain = remain.minus ( m ) ;
}
ONE.moveLeftTo ( total , m ) ;
t = m.minus ( t ) ;
while ( t.total < total )
t[t.total ++] = 0 ;
var v , c = CAL / key , p = POW / key , u = 1 << UNIT ;
for ( i -- , j -- ; i > -1 ; i -- , j -- )
{
v = remain[j] == last
? BITMASK
: Math.floor ( remain[j] * p + ( remain[j - 1] + u ) * c ) ;
if ( v <= ( remain[j] += t.getMultiBit ( 0 , v , remain , i , 0 , total ) ) )
continue ;
t.moveLeftTo ( i , m ) ;
remain = remain.minus ( m ) ;
for ( ; v >= remain[j] ; v -- )
remain = remain.minus ( m ) ;
}
remain.reset ( total ) ;
if ( bit > 0 )
remain.shiftRightTo ( bit , remain ) ;
if ( this.start < 0 )
remain = ZERO.minus ( remain ) ;
} ,
/**
* 현재 값을 e 로 제곱하고 n 으로 나눈 나머지 값을 반환한다.
* @param BigInt e 제곱 값
* @param BigInt n 나눌 값 ( RSA 암/복호화 공통키 n 임 )
* @see pow ( 문자열 , e ) % this.n
*/
powMod: function ( e , n )
{
var bit = e.getBitLength () , lem = 6 ;
if ( bit < 18 )
lem = 1 ;
else if ( bit < 48 )
lem = 3 ;
else if ( bit < 144 )
lem = 4 ;
else if ( bit < 768 )
lem = 5 ;
var value = [] , lm = lem - 1 , lk = ( 1 << lem ) - 1 ,
t = new BigInt , i ;
this.moveLeftTo ( n.total , t ) ;
t.modTo ( n , t ) ;
n.modular () ;
value[1] = this.start < 0 && t.diff ( ZERO ) > 0 ? n.minus ( t ) : t ;
if ( lem > 1 )
{
t = new BigInt ;
n.squareTo ( value[1] , t ) ;
for ( i = 3 ; i <= lk ; i += 2 )
n.multiplyTo ( t , value[i - 2] , value = new BigInt ) ;
}
var r1 = new BigInt ( 1 ) , r2 = new BigInt ,
j = e.total - 1 , q , k ;
for ( i = e[j].toString ( 2 ).length - 1 ; j >= 0 ; )
{
q = i >= lm
? ( e[j] >> ( i - lm ) ) & lk
: ( ( e[j] & ( ( 1 << ( i + 1 ) ) - 1 ) ) << ( lm - i ) ) + ( j > 0 ? e[j - 1] >> ( BIT + i - lm ) : 0 ) ;
for ( k = lem ; ( q & 1 ) == 0 ; k -- )
q >>= 1 ;
if ( ( i -= k ) < 0 )
i += BIT , j -- ;
if ( r1.total == 1 )
r1.overwrite ( value[q] ) ;
else
{
for ( ; k > 1 ; k -= 2 )
n.squareTo ( r1 , r2 ) , n.squareTo ( r2 , r1 ) ;
if ( k > 0 )
n.squareTo ( r1 , r2 ) ;
else
r1 = [r2 , r2 = r1][0] ;
n.multiplyTo ( r2 , value[q] , r1 ) ;
}
while ( j > -1 && ( e[j] & ( 1 << i ) ) == 0 )
{
n.squareTo ( r1 , r2 ) ;
r1 = [r2 , r2 = r1][0] ;
if ( -- i < 0 )
i = BIT - 1 , j -- ;
}
}
n.reduce ( r1 ) ;
return r1 ;
} ,
/**
* 몽고메리(Montgomery) 모듈러 초기화
*/
modular: function ()
{
if ( this.point )
return ;
if ( this.total < 1 || ( this[0] & 1 ) == 0 )
this.point = 0 ;
else
{
var x = this[0] & 3 ;
for ( var i = 4 ; i < 17 ; i = i * 2 )
x = x * ( 2 - ( this[0] & HEX ) * x ) & HEX ;
x = x * ( 2 - this[0] * x & BITMASK ) & BITMASK ;
this.point = x > 0 ? BITMAX - x : -x ;
}
this.split = this.point & HEX['15'] ;
this.mod = this.point >> 15 ;
this.mask = ( 1 << ( BIT - 15 ) ) -1 ;
this.double = 2 * this.total ;
} ,
/**
* 모듈러 곱 연산 결과를 result 에 할당한다.
* @param BitInt source 곱할 값
* @param BitInt target 곱할 값
* @param BitInt result 결과 값
*/
multiplyTo: function ( source , target , result )
{
for ( var i = 0 ; i < source.total ; i ++ )
result = 0 ;
for ( i = 0 ; i < target.total ; i ++ )
result[i + source.total] = source.getMultiBit ( 0 , target , result , i , 0 , source.total ) ;
result.reset ( source.total + target.total , 0 ) ;
this.reduce ( source.start == target.start ? result : ZERO.minus ( result ) ) ;
} ,
/**
* 모듈러 제곱근(루트) 연산 결과를 result 에할 할당한다.
* @param BitInt target 제곱근
* @param BitInt result 결과 값
*/
squareTo: function ( target , result )
{
result.total = target.total * 2 ;
for ( i = result.total - 1 ; i > -1 ; i -- )
result = 0 ;
var total = target.total - 1 ;
for ( i = 0 ; i < total ; i ++ )
{
var c = target.getMultiBit ( i , target , result , 2 * i , 0 , 1 ) ;
if ( ( result[i + target.total] += target.getMultiBit ( i + 1 , 2 * target , result , 2 * i + 1 , c , target.total - i - 1 ) ) > BITMASK )
{
result[i + target.total] -= BITMAX ;
result[i + target.total + 1] = 1 ;
}
}
if ( result.total > 0 )
result[result.total - 1] += target.getMultiBit ( i , target , result , 2 * i , 0 , 1 ) ;
result.reset ( result.total , 0 ) ;
this.reduce ( result ) ;
} ,
/**
* 모듈려 연산을 수행한다.
* @param BigInt target 연산 대상 값
*/
reduce: function ( target )
{
while ( target.total <= this.double )
target[target.total ++] = 0 ;
for ( var i = 0 , j , v ; i < this.total ; i ++ )
{
j = target & HEX['15'] ;
v = j * this.split + ( ( j * this.mod + ( target >> 15 ) * this.split & this.mask ) << 15 ) & BITMASK ;
j = i + this.total ;
target[j] += this.getMultiBit ( 0 , v , target , i , 0 , this.total ) ;
while ( target[j] > BITMASK )
target[j] -= BITMAX , target[++ j] ++ ;
}
target.reset () ;
target.moveRightTo ( this.total , target ) ;
if ( target.diff ( this ) > -1 )
target = target.minus ( this ) ;
}
}
/**
* 브라우저에 따른 비트 수 제한과 멀티비트 추출 함수 교체
*/
var BIT = 28 ,
FAR = ( ( 0xdeadbeefcafe & HEX['28'] ) == 0xefcafe ) ;
if ( FAR && navigator.appName == 'Microsoft Internet Explorer' )
BIT = 30 ;
else if ( FAR && navigator.appName != 'Netscape' )
{
BIT = 26 ;
BigInt.prototype.getMultiBit = function ( i , value , target , j , result , repeat )
{
for ( var v ; repeat > 0 ; repeat -- )
{
v = value * this[i ++] + target[j] + result ;
result = Math.floor ( v / 0x4000000 ) ;
target[j ++] = v & HEX[BIT] ;
}
return result ;
}
}
/**
* 상수 선언
*/
var BITMAX = 1 << BIT ,
BITMASK = ( BITMAX ) - 1 ,
UNIT = 2 * BIT - 52 , // 28bit = 100, 30bit = 1000, 26bit = 0
POW = Math.pow ( 2 , 52 ) ,
CAL = 1 << 52 - BIT ,
ZERO = new BigInt ( 0 ) ,
ONE = new BigInt ( 1 ) ;
})();
function getpass(m){
var a = ssRsa();
return a.encrypt(m);
}
源码上传了,谢谢!
主要是测一下自己的JS调试能力,太小白了(大神们不要笑话),调试的是这个网址:http://pz-2015.com/main_login.php?move_pc_screen=