#!/usr/bin/perl -U
#
# v0.02 (c)mahatma, no warranty, 12/2004
#
# RSA code (c) John Hanna 2004, GPL, http://shop-js.sf.net, 10/13/2004
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
# optional:
#use MD5; my $use_MD5=1; # uncomment to use faster MD5 lib
use Math::BigInt; my $use_BigInt=1; # comment to no RSA (for $auth==1)
my $cgi = new CGI;
my $session="$ENV{REMOTE_ADDR} $ENV{HTTP_X_FORWARDED_FOR}";
my %b64;
my $b64s='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"';
{my $n=0; for (split(//,$b64s)) {$b64{$_}=$n++}}
umask 0177;
### config start
## $auth - password: 0-none/.htpasswd; 1:crypt; 2:unencrypted; 3:md5
## 1 - RSA encrypted login; 2,3 - md5 hashed;
my $auth=0;
## RSA login only ($auth==1 && $use_BigInt==1):
## NOW you MUST generate own keys: http://shop-js.sf.net/crypto2.htm
## other ways may be in new version
my @pub_rsa_key=(136867779,84822705,160);
my $priv_rsa_key=[[14636137,3346344,66],[230684127,11],[139074205,13]];
my $pub_rsa_e=17;
## don't touch this (better):
my ($user,$password,@sig) = $auth==0?($ENV{REMOTE_USER},''):login_get();
my $passwd=""; # passwords filename ($auth!=0)
my %hpasswd; # predefined or buffer
## you may use own password database (undef $passwd first):
#dbmopen(%hpasswd,'/etc/dbpasswd/dbpasswd',600);
## or you may enter own login:
#$hpasswd{'user'}='password';
my $base="./";
my $webbase="/";
my $iam=$ENV{SCRIPT_NAME};
my $secure=0; # 0:none; 1:uid/gid; 2:1+deny chown/chmod
my @suid;
## for upload:
#$cgi::POST_MAX = 1048576; # max to upload
#my $temp='/tmp/'; # undef = direct
#my $mv='/bin/mv'; # if $temp defined only
### config end
### alt config - standard multi-user unix hosting example, exec as root
#my $auth=1;
#my @pub_rsa_key=(136867779,84822705,160);
#my $priv_rsa_key=[[14636137,3346344,66],[230684127,11],[139074205,13]];
#my $pub_rsa_e=17;
#my ($user,$password,@sig) = $auth==0?($ENV{REMOTE_USER},''):login_get();
#my $passwd="/etc/shadow";
#my %hpasswd;
#my $base="/home/$user/public_html/";
#my $webbase="/~$user/";
#my $iam=$ENV{SCRIPT_NAME};
#my $secure=1;
#my @suid=($user,$user);
##$cgi::POST_MAX = 1048576;
##my $temp='/tmp/';
##my $mv='/bin/mv';
### alt config end
my @md5_i=(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9);
my @md5_s=(7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21);
my @md5_t=(0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391);
#push (@INC, "/home/~$user");
#$ENV{PATH}="/home/~$user";
my $header="Content-type: text/html\n\n";
my $head='
';
my $error;
my $path=param('path')||'';
my $action=param('action')||'start';
my @item;
my $lastpath='';
my $it;
for(my $i=0;$i<65535 && defined($it=param("item$i")) && $it ne '';$i++){
push @item,param("item$i");
};
### install ###
install() if($ARGV[0] eq install);
if($action eq 'menu'){a_menu();ex(0)}
elsif($action eq 'start'){a_start();ex(0)}
### /install ###
if(!login()){
$error.='Invalid login ' if($user ne '');
$error.='Not logged in!';
$user=$password='';
@item=();
a_ls();
ex(-2);
}
seq() if($secure>0);
if($action eq 'ls' || $action eq 'reload'){a_lsd()}
elsif($action eq 'get'){a_get()}
elsif($action eq 'upload'){a_upload()}
elsif($action eq 'delete'){a_rm()}
elsif($action eq 'mkdir'){a_mkdir()}
elsif($action eq 'chmod'){a_chmod()}
elsif($action eq 'chown'){a_chown()}
elsif($action eq 'link'){a_link()}
elsif($action eq 'symlink'){a_symlink()}
elsif($action eq 'logoff'){a_logoff()}
else{zerr("Invalid command \"$action\"")}
ex(0);
### login ###
sub login_get{
my $i=param('sig');
$i=rsaDecode($priv_rsa_key,$i) if($auth==1&&$use_BigInt&&$i ne '');
my @s=split(/:/,$i);
for($i=0;$i<=$#s;$i++){@s[$i]=unesc(@s[$i])}
return @s;
}
sub login_js{
my $t='p';
$t="md5h($t)" if($auth==3);
$t="md5h($t+t+s)" if($auth>1);
$t="escape(fm1.document.f.item0.value)+':'+escape($t)+':'+escape(t)";
$t.="+':'+escape(s)" if($auth==1);
$t="rsaEncode([$pub_rsa_e],".a2js("%u",@pub_rsa_key).",$t)" if ($auth==1&&$use_BigInt);
$t=qq(
var sig='';
function setpass(p,t,s){sig=$t}
function sign(f){f.sig.value=sig}
function logoff(){sig=''}
);
$t=md5h_js().$t if(index($t,'md5h',0)>=0);
$t=RSA_js().$t if(index($t,'rsa',0)>=0);
return $t;
}
sub login{
return 1 if($auth==0);
my $u,$p,$l;
if(defined($passwd)){
open PF,"<$passwd" or return 0;
while(defined($l=)){
($u,$p)=(split(/:/, $l))[0,1];
if($u eq $user){
$hpasswd{$u}=$p;
last;
}
}
close(PF);
}
return 0 if(!defined($p=$hpasswd{$user}));
if($auth==1){
return 0 if(@sig[1] ne $session);
$password=crypt($password,$p)
}else{
$p=md5h("$p@sig[0]$session");
}
return ($password eq $p);
}
sub logoff{
@sig=[];
$user=$password='';
}
### /login ###
sub md5h{
my ($s,$a,$b,$c,$d,$xx)=(shift,0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xffffffff);
return MD5->hexhash($s) if($use_MD5);
my $e,$m,$i,$j,@x;
my $l=length($s);
my $n=((($l+8)>>6)+1)<<4;
$xx++;
for($i=0;$i<$n;$i++) {@x[$i]=0}
$s.="\x80";
for($i=0;$i<=$l;$i++) {@x[$i>>2]|=(ord(substr($s,$i,1))&0xFF)<<(($i&3)<<3)}
@x[$n-2]=$l<<3;
for($i=0;$i<$n;$i+=16){
my ($a1,$b1,$c1,$d1)=($a,$b,$c,$d);
for($j=0;$j<64;$j++){
$e=(((($m=($a+@x[$i+@md5_i[$j]]+@md5_t[$j]+(($e=$j>>4)==0?($b&$c)|($d&~$b):$e==1?($b&$d)|($c&~$d):$e==2?$b^$c^$d:$c^($b|~$d)))%$xx)<<($l=@md5_s[$e<<2|($j&3)]))|($m>>(32-$l))&((1<<$l)-1))+$b)%$xx;
$a=$d;$d=$c;$c=$b;$b=$e;
}
$a=($a+$a1)%$xx;$b=($b+$b1)%$xx;$c=($c+$c1)%$xx;$d=($d+$d1)%$xx;
}
my @r=($a,$b,$c,$d),$h='';
for($i=0;$i<16;$i++) {$h.=sprintf("%x%x",@r[$j=$i>>2]>>4&15,@r[$j]&15);@r[$j]>>=8;}
return $h;
}
##################################################################
### rsa ###
sub rc4 {
my ($key, $string)=@_;
#"""Return string rc4 (de/en)crypted with RC4."""
my($i,$j,$klen,@s)=(0,0,length($key),0 .. 255);
for(0 .. 1) {
for $i (0 .. 255) {
$j=(ord(substr($key,$i%$klen,1))+$s[$i]+$j)%256;
($s[$i],$s[$j])=($s[$j],$s[$i])
}
}
my $r='';
for $i (0 .. length($string)-1) {
my $i2=$i % 256;
$j=($s[$i2]+$j)%256;
($s[$i2],$s[$j])=($s[$j],$s[$i2]);
$r.=chr(ord(substr($string,$i,1))^$s[($s[$i2]+$s[$j])%256]);
}
return $r;
}
sub crt_RSA {
my ($m, $d, $p, $q)=@_;
#""" Compute m**d mod p*q for RSA private key operations."""
return $m->bmodpow($d,$p*$q);
}
sub base64ToText {
my $text=shift;
my ($r,$m,$a,$c)=('',0,0,0);
for $i (0 .. length($text)-1) {
$c=$b64{substr($text,$i,1)};
#print substr($text,$i,1),"=$i=$c|\n";
if(defined $c) {
$r .= chr(($c << (8-$m))& 255 | $a) if $m;
$a = $c >> $m;
$m=($m+2) % 8;
}
}
return $r;
}
sub t2b { my $s=shift;
my $r=Math::BigInt->bzero();
my $m=Math::BigInt->bone();
for $i (0 .. length($s)-1) {
$r+=$m*ord(substr($s,$i,1));
$m*=256;
}
return $r
}
sub b2t { my $b=shift;
my $r='';
while($b) {
$r.=chr($b % 256);
$b/=256;
}
return $r;
}
sub fix { my $a=shift;
my $r=Math::BigInt->bzero();
my $s=0;
for $i (@$a) {
$r+=Math::BigInt->new($i) << $s;
$s+=28;
}
return $r;
}
sub rsaDecode { my ($key,$text)=@_;
#""" decode the text based on the given rsa key. """
# separate the session key from the text
$text=base64ToText($text);
my $sessionKeyLength=ord(substr($text,0,1));
my $sessionKeyEncryptedText=substr($text,1,$sessionKeyLength);
$text=substr($text,$sessionKeyLength+1);
my $sessionKeyEncrypted=t2b($sessionKeyEncryptedText);
# un-rsa the session key
my $sessionkey=crt_RSA($sessionKeyEncrypted,fix($key->[0]),fix($key->[1]),fix($key->[2]));
$sessionkey=b2t($sessionkey);
$text=rc4($sessionkey,$text);
return $text
}
### /rsa ###
sub err_{
my $e=shift;
return "$!; $action \"$e\" ";
}
sub ex{
exit shift;
}
sub seq{
my $u=defined(@suid[0])?(getpwnam(@suid[0]) or &zerr("uid:\"@suid[0]\"")):-1;
my $g=defined(@suid[1])?(getgrnam(@suid[1]) or &zerr("gid:\"@suid[1]\"")):-1;
$)="$g $g"; $(=$g; $<=$>=$u;
if($) ne "$g $g" or $(!=$g or $!=$u){
print "$header Security error (set uid/gid)";
&ex(-3);
}
}
sub seq2{
&zerr('Denyed') if($secure==2);
}
sub chk{
my $n=unesc(shift);
my @d=split(/\//,$n);
for (my $i=0;$i<=$#d;$i++){
if(@d[$i] eq '.' or @d[$i] eq ''){
splice(@d,$i,1);
$i-- if($i>-1);
}elsif(@d[$i] eq '..'){
if($i>0){splice(@d,--$i,2)}
else{splice(@d,$i,1)};
$i-- if($i>-1);
}
}
$n='';
my $f=pop(@d);
for my $i(@d) {$n.=$i.'/'};
$n.=$f;
return $n;
}
sub a_logoff{
$error.='Logged out!';
logoff();
@item=();
a_ls();
}
sub a_get{
for my $it(@item){
my @s=stat(my $n=$base.(my $i=&chk("$path$it")));
# err($n) if(!$s);
# if(-d $n){
if(@s[2]&0x4000){
$lastpath=$path;
$path=$i;
$path.='/' if($path ne '');
a_lsd();
}else{
open FH,"<$n" or err($it);
print "Content-type: application/unknown\nContent-Length: @s[7]\nLast-Modified: ".localtime(@s[9])."\nContent-Transfer-Coding: binary\nContent-Disposition: download; filename=\"$it\"\n\n", or err($it);
close(FH);
}
}
}
sub a_upload{
for my $it(@item){
my @n=split(/[\\\/:]/,$it);
my $d=&chk($path.pop(@n));
my $f=defined($temp)?"$temp$user.".time.".tmp":"$base$d";
open FH, ">$f" or err($it);
# chown @own[0],@own[1],$f or err($it.rm()) if(defined(@own));
# binmode FH;
print FH <$it> or err($it.rm());
close (FH);
`$mv -f $f $base$d` if(defined($temp));
}
a_lsd();
sub rm{
close FH;
unlink FH;
return '';
}
}
sub a_link{
for my $its(@item){for my $it(split(/,/,$its)){
my ($l,$ll)=split(/:/,$it,2);
link $base.&chk($ll),$base.&chk($l) or &err("$l -> $ll");
}}
a_lsd();
}
sub a_symlink{
for my $its(@item){for my $it(split(/,/,$its)){
my ($l,$ll)=split(/:/,$it,2);
my @l0=split(/\//,&chk($l));
my @l1=split(/\//,&chk($ll));
my $n=0;
my $i;
for($i=0;($i<=$#l0)&&(@l0[$i] eq @l1[$i]);$i++){ $n++};
splice(@l0,0,$n);
splice(@l1,0,$n);
$ll='';
my $f=pop(@l1);
for($i=0;$i<$#l0;$i++) {$ll.='../'};
for $i(@l1) {$ll.=$i.'/'};
$ll.=$f;
symlink $ll,"$base$l" or &err("$l -> $ll");
}}
a_lsd();
}
sub a_mkdir{
for my $it(@item){mkdir($base.&chk("$path$it")) or err(&chk("$path$it"))}
a_lsd();
}
sub a_rm{
for my $its(@item){for my $it(split(/,/,$its)){
my $n=$base.&chk("$path$it");
if(-l $n) {unlink($n) or err($it)}
elsif(-d $n) {rmdir($n) or err($it)}
else{unlink($n) or err($it);}
}};
a_lsd();
};
sub a_chmod{
seq2();
for my $its(@item){for my $it(split(/,/,$its)){
my @it1=split(/:/,$it,2); #### try 1 or 2!!!
@it1[1]=$base.&chk($path.@it1[1]);
chmod @it1 or err($it);
}};
a_lsd();
};
sub zerr{
my $e=shift;
$error.="$e ";
a_lsd();
&ex(-1);
}
sub a_chown{
seq2();
for my $its(@item){
my @its1=split(/,/,$its);
my @u=split(/:/,pop(@its1));
my @uid;
if(@u[0] && @u[0] ne '') {($uid=getpwnam(@u[0])) or &zerr(@u[0]);}
my $gid;
if(@u[1] && @u[1] ne '') {($gid=getgrnam(@u[1])) or &zerr(@u[1]);}
for my $it(@its1){
chown $uid||-1,$gid||-1,$base.&chk("$path$it") or err($it);
}
}
a_lsd();
}
##################################################################
sub err{
$error.=&err_(shift||'');
a_lsd();
&ex(-1);
}
sub a_lsd{
@item=('');
a_ls();
}
sub esc{
my $x=shift;
#$x=~s/([\x00-\x29\x2c\x3a-\x3f\x5b-\x5e\x60\x7b-\x7f])/sprintf('%%%02X',ord($1))/eg;
$x=~s/([\x00-\x1f,:\"\'\\])/sprintf('%%%02X',ord($1))/eg;
return $x;
}
sub unesc{
my $x=shift;
$x=~s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
return $x;
}
sub a_ls{
my $e='';
my $err;
my $t=qq($header$head
";
if($auth!=0 && $user eq ''){
$ret=qq(parent.click\("ls",""\););
$x=qq( $session Login:
$x);
$t.=" onload='document.f.item0.focus()'";
}
$e.=qq();
}else{$t.=" onload=\'$ret\'";};
$t.=">$e";
print $t;
};
### install ###
sub a2js{
my ($f,$s,$c)=(shift,'[','');
for my $x(@_){
$s.=$c.sprintf($f,$x);
$c=',';
}
return "$s]";
}
sub md5h_js{
return "var md5_i=".&a2js("%u",@md5_i).",\nmd5_s=".&a2js("%u",@md5_s).",\nmd5_t=".&a2js("0x%x",@md5_t).qq(,nums='0123456789abcdef'.split('');
function s32(x,y){
var l=(x&0xFFFF)+(y&0xFFFF);
return (((x>>16)+(y>>16)+(l>>16))<<16)|(l&0xFFFF);
}
function md5h(s){
var a=0x67452301,b=0xefcdab89,c=0x98badcfe,d=0x10325476,e,m,l=s.length,n=(((l+8)>>6)+1)<<4,i,j,x=[];
for(i=0;i>2]|=(s.charCodeAt(i)&0xFF)<<((i&3)<<3);
x[i>>2]|=0x80<<((i&3)<<3);
x[n-2]=l<<3;
for(i=0;i>4)==0?(b&c)|(d&~b):e==1?(b&d)|(c&~d):e==2?b^c^d:c^(b|~d))),s32(x[i+md5_i[j]],md5_t[j])))<<(l=md5_s[e<<2|(j&3)]))|(m>>>(32-l))),b);
a=d;d=c;c=b;b=e;
}
a=s32(a1,a);b=s32(b1,b);c=s32(c1,c);d=s32(d1,d);
}
var r=[a,b,c,d],h='';
for(i=0;i<16;i++) {h+=nums[r[j=i>>2]>>4&15]+nums[r[j]&15];r[j]>>=8;}
return h;
}
);
}
# - suggested (not sure):
# "e=s32..."-> e=(((m=a+((e=j>>4)==0?(b&c)|(d&~b):e==1?(b&d)|(c&~d):e==2?b^c^d:c^(b|~d))+x[i+md5_i[j]]+md5_t[j])<<(l=md5_s[e<<2|(j&3)]))|(m>>>(32-l)))+b;
# "a=s32..."-> a+=a1;b+=b1;c+=c1;d+=d1;
# and remove "s32" func
sub RSA_js{
< bs=16, 64bit -> bs=32
// bm is the mask, bs is the shift
//bm=0xf; bs=4; // low base useful for testing if digits handled ok
bs=28;
bx2=1<>1; bd=bs>>1; bdm=(1 << bd) -1
log2=Math.log(2)
function badd(a,b) { // binary add
var al=a.length, bl=b.length
if(al < bl) return badd(b,a)
var c=0, r=[], n=0
for(; n>>=bs
}
for(; n>>=bs
}
if(c) r[n]=c
return r
}
function beq(a,b) { // returns 1 if a == b
if(a.length != b.length) return 0
for(var n=a.length-1; n>=0; n--)
if(a[n] != b[n]) return 0
return 1
}
function bsub(a,b) { // binary subtract
var al=a.length, bl=b.length, c=0, r=[]
if(bl > al) {return []}
if(bl == al) {
if(b[bl-1] > a[bl-1]) return []
if(bl==1) return [a[0]-b[0]]
}
for(var n=0; n>=bs
}
for(;n>=bs
}
if(c) {return []}
if(r[n-1]) return r
while(n>1 && r[n-1]==0) n--;
return r.slice(0,n)
}
function bmul(a,b) { // binary multiply
b=b.concat([0])
var al=a.length, bl=b.length, r=[], n,nn,aa, c, m
var g,gg,h,hh, ghhb
for(n=al+bl; n>=0; n--) r[n]=0
for(n=0; n>bd; h=aa & bdm
m=n
for(nn=0; nn>bd; g=g & bdm
//(gg*2^15 + g) * (hh*2^15 + h) = (gghh*2^30 + (ghh+hgg)*2^15 +hg)
ghh = g * hh + h * gg
ghhb= ghh >> bd; ghh &= bdm
c += r[m] + h * g + (ghh << bd)
r[m] = c & bm
c = (c >> bs) + gg * hh + ghhb
}
}
}
n=r.length
if(r[n-1]) return r
while(n>1 && r[n-1]==0) n--;
return r.slice(0,n)
}
function blshift(a,b) {
var n, c=0, r=[]
for(n=0; n>=bs
}
if(c) r[n]=c
return r
}
function brshift(a) {
var c=0,n,cc, r=[]
for(n=a.length-1; n>=0; n--) {
cc=a[n]; c<<=bs
r[n]=(cc | c)>>1
c=cc & 1
}
while(r.length > 1 && r[r.length-1]==0) {
r=r.slice(0,-1)
}
this.a=r; this.c=c
return this
}
function zeros(n) {var r=[]; while(n-->0) r[n]=0; return r}
function toppart(x,start,len) { var n=0
while(start >= 0 && len-->0) n=n*bx2+x[start--]
return n
}
//14.20 Algorithm Multiple-precision division from HAC
function bdiv(x,y) {
var n=x.length-1, t=y.length-1, nmt=n-t
// trivial cases; x < y
if(n < t || n==t && (x[n]0 && x[n]==y[n] && x[n-1]0; i--) y[i]=((y[i]<> shift2); y[0]=(y[0]<0; i--) x[i]=((x[i]<> shift2); x[0]=(x[0]<t; i--) {
m=i-t-1
if(i >= x.length)
q[m]=1
else if(x[i] == yt)
q[m]=bm
else
q[m]=Math.floor(toppart(x,i,2)/yt)
topx=toppart(x,i,3)
while(q[m] * top > topx)
q[m]--
//x-=q[m]*y*b^m
y2=y2.slice(1)
x2=bsub(x,bmul([q[m]],y2))
if(x2.length==0) {
q[m]--
x2=bsub(x,bmul([q[m]],y2))
}
x=x2
}
// de-normalize
if(shift) {
for(i=0; i>shift) | ((x[i+1] << shift2) & bm); x[x.length-1]>>=shift
}
while(q.length > 1 && q[q.length-1]==0) q=q.slice(0,q.length-1)
while(x.length > 1 && x[x.length-1]==0) x=x.slice(0,x.length-1)
this.mod=x
this.q=q
return this
}
function bmod(p,m) { // binary modulo
if(m.length==1) {
if(p.length==1) return [p[0] % m[0]]
if(m[0] < bdm) return [simplemod(p,m[0])]
}
var r=bdiv(p,m)
return r.mod
}
function simplemod(i,m) {
// returns the mod where m < 2^bd
if(m>bdm)
return mod(i,[m])
var c=0, v
for(var n=i.length-1; n>=0; n--) {
v=i[n]
c=((v >> bd) + (c<=0; n--) mu[n]=0; mu=bdiv(mu,m).q
for(n=0; n 0) {
return bmod2(x.slice(0,xl).concat(bmod2(x.slice(xl),m,mu)),m,mu)
}
var ml1=m.length+1, ml2=m.length-1,rr
//var q1=x.slice(ml2)
//var q2=bmul(q1,mu)
var q3=bmul(x.slice(ml2),mu).slice(ml1)
var r1=x.slice(0,ml1)
var r2=bmul(q3,m).slice(0,ml1)
var r=bsub(r1,r2)
//var s=('x='+x+'\\nm='+m+'\\nmu='+mu+'\\nq1='+q1+'\\nq2='+q2+'\\nq3='+q3+'\\nr1='+r1+'\\nr2='+r2+'\\nr='+r);
if(r.length==0) {
r1[ml1]=1
r=bsub(r1,r2)
}
for(var n=0;;n++) {
rr=bsub(r,m)
if(rr.length==0) break
r=rr
if(n>=3) return bmod2(r,m,mu)
}
return r
}
function sub2(a,b) {
var r=bsub(a,b)
if(r.length==0) {
this.a=bsub(b,a)
this.sign=1
} else {
this.a=r
this.sign=0
}
return this
}
function signedsub(a,b) {
if(a.sign) {
if(b.sign) {
return sub2(b,a)
} else {
this.a=badd(a,b)
this.sign=1
}
} else {
if(b.sign) {
this.a=badd(a,b)
this.sign=0
} else {
return sub2(a,b)
}
}
return this
}
function modinverse(x,n) { // returns x^-1 mod n
// from Bryan Olson
var y=n.concat(), t, r, bq, a=[1], b=[0], ts
a.sign=0; b.sign=0
while( y.length > 1 || y[0]) {
t=y.concat()
r=bdiv(x,y)
y=r.mod
q=r.q
x=t
t=b.concat(); ts=b.sign
bq=bmul(b,q)
bq.sign=b.sign
r=signedsub(a,bq)
b=r.a; b.sign=r.sign
a=t; a.sign=ts
}
if(beq(x,[1])==0) return [0] // No inverse; GCD is x
if(a.sign) {
a=bsub(n,a)
}
return a
}
function crt_RSA(m, d, p, q) {
// Compute m**d mod p*q for RSA private key operations. -- Bryan Olson via deja.com
var xp = bmodexp(bmod(m,p), bmod(d,bsub(p,[1])), p)
var xq = bmodexp(bmod(m,q), bmod(d,bsub(q,[1])), q)
var t=bsub(xq,xp);
if(t.length==0) {
t=bsub(xp,xq)
t = bmod(bmul(t, modinverse(p, q)), q);
t=bsub(q,t)
} else {
t = bmod(bmul(t, modinverse(p, q)), q);
}
return badd(bmul(t,p), xp)
}
// conversion functions:
// text to binary and binary to text, text to base64 and base64 to text
// OK, so this isn't exactly base64 -- fix it if you care
function t2b(s) {
var bits=s.length*8, bn=1, r=[0], rn=0, sn=0, sb=1;
var c=s.charCodeAt(0)
for(var n=0; n bm) {bn=1; r[++rn]=0; }
if(c & sb) r[rn]|=bn;
bn<<=1
if((sb<<=1) > 255) {sb=1; c=s.charCodeAt(++sn); }
}
return r;
}
function b2t(b) {
var bits=b.length*bs, bn=1, bc=0, r=[0], rb=1, rn=0
for(var n=0; n 255) {rb=1; r[++rn]=0; }
if((bn<<=1) > bm) {bn=1; bc++; }
}
while(r[rn]==0) {rn--;}
var rr=''
for(var n=0; n<=rn; n++) rr+=String.fromCharCode(r[n]);
return rr;
}
b64s='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"'
function textToBase64(t) {
var r=''; var m=0; var a=0; var tl=t.length-1; var c
for(n=0; n<=tl; n++) {
c=t.charCodeAt(n)
r+=b64s.charAt((c << m | a) & 63)
a = c >> (6-m)
m+=2
if(m==6 || n==tl) {
r+=b64s.charAt(a)
if((n%45)==44) {r+="\\n"}
m=0
a=0
}
}
return r
}
function base64ToText(t) {
var r=''; var m=0; var a=0; var c
for(n=0; n= 0) {
if(m) {
r+=String.fromCharCode((c << (8-m))&255 | a)
}
a = c >> m
m+=2
if(m==8) { m=0 }
}
}
return r
}
// RC4 stream encryption
// adapted from www.cpan.org crypt::rc4 -- thanks!
function rc4(key, text) {
var i, x, y, t, x2, kl=key.length;
s=[];
for (i=0; i<256; i++) s[i]=i
y=0
for(j=0; j<2; j++) {
for(x=0; x<256; x++) {
y=(key.charCodeAt(x%kl) + s[x] + y) % 256
t=s[x]; s[x]=s[y]; s[y]=t
}
}
var z=""
for (x=0; x>n) | ((a<<(8-n))&255)):a;}
function hash(s,l) {
var sl=s.length,r=[],rr='',v=1,lr=4;
for(var n=0; n