source: Dev/branches/rest-dojo-ui/client/dojox/encoding/crypto/RSAKey-ext.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 3.3 KB
Line 
1define([
2        "dojo/_base/kernel", // dojo.experimental
3        "dojo/_base/lang", // dojo.extend
4        "./RSAKey",
5        "../../math/BigInteger-ext"
6], function(kernel, lang, RSAKey, BigInteger) {
7
8        kernel.experimental("dojox.encoding.crypto.RSAKey-ext");
9
10        // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
11        function pkcs1unpad2(d, n){
12                var b = d.toByteArray();
13                for(var i = 0, len = b.length; i < len && !b[i]; ++i);
14                if(b.length - i !== n - 1 || b[i] !== 2){
15                        return null;
16                }
17                for(++i; b[i];){
18                        if(++i >= len){
19                                return null;
20                        }
21                }
22                var ret = "";
23                while(++i < len){
24                        ret += String.fromCharCode(b[i]);
25                }
26                return ret;
27        }
28
29        lang.extend(RSAKey, {
30                setPrivate: function(N, E, D){
31                        // summary:
32                        //      Set the private key fields N, e, d and CRT params from hex strings
33                        if(N && E && N.length && E.length){
34                                this.n = new BigInteger(N, 16);
35                                this.e = parseInt(E, 16);
36                                this.d = new BigInteger(D, 16);
37                        }else{
38                                throw new Error("Invalid RSA private key");
39                        }
40                },
41                setPrivateEx: function(N, E, D, P, Q, DP, DQ, C) {
42                        // summary:
43                        //      Set the private key fields N, e, d and CRT params from hex strings
44                        if(N && E && N.length && E.length){
45                                this.n = new BigInteger(N, 16);
46                                this.e = parseInt(E, 16);
47                                this.d = new BigInteger(D, 16);
48                                this.p = new BigInteger(P, 16);
49                                this.q = new BigInteger(Q, 16);
50                                this.dmp1 = new BigInteger(DP, 16);
51                                this.dmq1 = new BigInteger(DQ, 16);
52                                this.coeff = new BigInteger(C, 16);
53                        }else{
54                                throw new Error("Invalid RSA private key");
55                        }
56                },
57                generate: function(B, E){
58                        // summary:
59                        //      Generate a new random private key B bits long, using public expt E
60                        var rng = this.rngf(), qs = B >> 1;
61                        this.e = parseInt(E, 16);
62                        var ee = new BigInteger(E, 16);
63                        for(;;) {
64                                for(;;) {
65                                        this.p = new BigInteger(B - qs, 1, rng);
66                                        if(!this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) && this.p.isProbablePrime(10)){
67                                                break;
68                                        }
69                                }
70                                for(;;) {
71                                        this.q = new BigInteger(qs, 1, rng);
72                                        if(!this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) && this.q.isProbablePrime(10)){
73                                                break;
74                                        }
75                                }
76                                if(this.p.compareTo(this.q) <= 0) {
77                                        var t = this.p;
78                                        this.p = this.q;
79                                        this.q = t;
80                                }
81                                var p1 = this.p.subtract(BigInteger.ONE);
82                                var q1 = this.q.subtract(BigInteger.ONE);
83                                var phi = p1.multiply(q1);
84                                if(!phi.gcd(ee).compareTo(BigInteger.ONE)) {
85                                        this.n = this.p.multiply(this.q);
86                                        this.d = ee.modInverse(phi);
87                                        this.dmp1 = this.d.mod(p1);
88                                        this.dmq1 = this.d.mod(q1);
89                                        this.coeff = this.q.modInverse(this.p);
90                                        break;
91                                }
92                        }
93                        rng.destroy();
94                },
95
96                decrypt: function(ctext){
97                        // summary:
98                        //      Return the PKCS#1 RSA decryption of "ctext".
99                        // ctext: String:
100                        //      an even-length hex string
101                        // returns: a plain string.
102                        var c = new BigInteger(ctext, 16), m;
103                        if(!this.p || !this.q){
104                                m = c.modPow(this.d, this.n);
105                        }else{
106                                // TODO: re-calculate any missing CRT params
107                                var cp = c.mod(this.p).modPow(this.dmp1, this.p),
108                                        cq = c.mod(this.q).modPow(this.dmq1, this.q);
109                                while(cp.compareTo(cq) < 0){
110                                        cp = cp.add(this.p);
111                                }
112                                m = cp.subtract(cq).multiply(this.coeff).mod(this.p).multiply(this.q).add(cq);
113                        }
114                        if(!m){
115                                return null;
116                        }
117                        return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
118                }
119        });
120       
121        return RSAKey;
122});
Note: See TracBrowser for help on using the repository browser.