RSA
# 1 原理
大整数分解困难, 因而暴露一个大整数是安全的。
## 1.1 过程
加密 M -> c, ( 公钥 N, e)
$ c \equiv M^e \quad (mod \; N) $
解密 c -> M, (私钥 N, d)
$ M \equiv c^d \quad (mod \; N) $
##1.2 公私钥生成
1. 随机生成两个素数 p,q
2. 计算 N=pq
3. 计算 欧拉数 $\psi(N)=(p-1)(q-1)$
4. 选取指数e, 满足 $ e \in (1,\psi(n)) 且与\psi(n)互质.实践中一般选e为一个素数, 如65537$
5. 计算e的乘法逆元d,满足 $ ed \equiv 1 \quad (mod\; \psi(n) ) $
6. 公钥 N和e, 私钥 N和d
##1.3 解密原理
根据一般化的欧拉定理,
$ 当 x \equiv y \quad (mod \; \psi(n))时, a^x \equiv a^y \quad (mod \; n) $
因为: $ ed \equiv 1 \quad (mod\; \psi(n) ) $
故有:$ M^{ed} \equiv M \quad (\mod \, N) $
又:$ c \equiv M^e \quad (\mod \, N) $
故根据同余指数性质:
$ c^d \equiv M^{ed} \equiv M \quad (mod \; n) $
#2 代码
```javascript
RSA = {}
RSA.math = {}
RSA.key = {"N":0,"E":0,"D":0}
RSA.math.powmod = function(a,e,m){
if( m == null) return Math.pow(a,e)
var ma = a % m, b = ma,i=1;
for(;i<e;i++){
b = b * ma % m
}
return b
}
RSA.math.rand = function(s,e){
if( e == null ){
e = s ; s = 0;
}
e = Math.max(s,e)
s = Math.min(s,e)
var r = Math.random(),d=e-s
return parseInt( d*r ) + s
}
RSA.math.prime = function(s){
if( s % 2 ==0) s += 1;
while( !this.isPrime(s)) s+=2;
return s;
}
RSA.math.isPrime = function(a){
if( a % 2 ==0) return 0
var e = parseInt(Math.sqrt(a)) +1,i=3;
while( i<e && a%i ) i+=2;
return i>=e
}
RSA.math.gcd = function(a,b){
if(a==0) {return b } else { while(b){ if(a>b) a=a-b; else b = b-a; }return a}
}
RSA.math.coprime = function(a){
for(var i=3;i<a;i++){
if( this.gcd(a,i) === 1) break;
}
return i<a?i:NaN
}
RSA.gen = function(a,b){
a = this.math.prime( a || this.math.rand(10,100) )
b = this.math.prime( b || this.math.rand(10,100) )
var npq = (a-1)*(b-1),e = this.math.coprime(npq)
if( String(e) == 'NaN' ){
return console.info('error:cannot find e')
}
var limit = Number.MAX_VALUE / 100 / Math.max(a,b)
for(var i=e+1;i<limit;i++){
if( i*e % npq === 1) break;
}
if( i >=limit ){
return console.info('error:cannot find d')
}
var d = i
this.key.N = a*b
this.key.E = e
this.key.D = d
this.key.data = {p:a,q:b,key:this.key}
return this
}
RSA.encode = function(m){
return this.math.powmod(m,this.key.E,this.key.N)
}
RSA.decode = function(e){
return this.math.powmod(e,this.key.D,this.key.N)
}
RSA.math = {}
RSA.key = {"N":0,"E":0,"D":0}
RSA.math.powmod = function(a,e,m){
if( m == null) return Math.pow(a,e)
var ma = a % m, b = ma,i=1;
for(;i<e;i++){
b = b * ma % m
}
return b
}
RSA.math.rand = function(s,e){
if( e == null ){
e = s ; s = 0;
}
e = Math.max(s,e)
s = Math.min(s,e)
var r = Math.random(),d=e-s
return parseInt( d*r ) + s
}
RSA.math.prime = function(s){
if( s % 2 ==0) s += 1;
while( !this.isPrime(s)) s+=2;
return s;
}
RSA.math.isPrime = function(a){
if( a % 2 ==0) return 0
var e = parseInt(Math.sqrt(a)) +1,i=3;
while( i<e && a%i ) i+=2;
return i>=e
}
RSA.math.gcd = function(a,b){
if(a==0) {return b } else { while(b){ if(a>b) a=a-b; else b = b-a; }return a}
}
RSA.math.coprime = function(a){
for(var i=3;i<a;i++){
if( this.gcd(a,i) === 1) break;
}
return i<a?i:NaN
}
RSA.gen = function(a,b){
a = this.math.prime( a || this.math.rand(10,100) )
b = this.math.prime( b || this.math.rand(10,100) )
var npq = (a-1)*(b-1),e = this.math.coprime(npq)
if( String(e) == 'NaN' ){
return console.info('error:cannot find e')
}
var limit = Number.MAX_VALUE / 100 / Math.max(a,b)
for(var i=e+1;i<limit;i++){
if( i*e % npq === 1) break;
}
if( i >=limit ){
return console.info('error:cannot find d')
}
var d = i
this.key.N = a*b
this.key.E = e
this.key.D = d
this.key.data = {p:a,q:b,key:this.key}
return this
}
RSA.encode = function(m){
return this.math.powmod(m,this.key.E,this.key.N)
}
RSA.decode = function(e){
return this.math.powmod(e,this.key.D,this.key.N)
}
```
posted on 2013-01-11 09:44 Simple Love 阅读(331) 评论(0) 编辑 收藏 举报