blob: 66baa276e241f0bc43475e8bd0831bed44a3b6fb [file] [log] [blame]
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -07001// Depends on jsbn.js and rng.js
2
3// Version 1.1: support utf-8 encoding in pkcs1pad2
4
5// convert a (hex) string to a bignum object
6function parseBigInt(str,r) {
7 return new BigInteger(str,r);
8}
9
10function linebrk(s,n) {
11 var ret = "";
12 var i = 0;
13 while(i + n < s.length) {
14 ret += s.substring(i,i+n) + "\n";
15 i += n;
16 }
17 return ret + s.substring(i,s.length);
18}
19
20function byte2Hex(b) {
21 if(b < 0x10)
22 return "0" + b.toString(16);
23 else
24 return b.toString(16);
25}
26
27// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
28function pkcs1pad2(s,n) {
29 if(n < s.length + 11) { // TODO: fix for utf-8
30 alert("Message too long for RSA");
31 return null;
32 }
33 var ba = new Array();
34 var i = s.length - 1;
35 while(i >= 0 && n > 0) {
36 var c = s.charCodeAt(i--);
37 if(c < 128) { // encode using utf-8
38 ba[--n] = c;
39 }
40 else if((c > 127) && (c < 2048)) {
41 ba[--n] = (c & 63) | 128;
42 ba[--n] = (c >> 6) | 192;
43 }
44 else {
45 ba[--n] = (c & 63) | 128;
46 ba[--n] = ((c >> 6) & 63) | 128;
47 ba[--n] = (c >> 12) | 224;
48 }
49 }
50 ba[--n] = 0;
51 var rng = new SecureRandom();
52 var x = new Array();
53 while(n > 2) { // random non-zero pad
54 x[0] = 0;
55 while(x[0] == 0) rng.nextBytes(x);
56 ba[--n] = x[0];
57 }
58 ba[--n] = 2;
59 ba[--n] = 0;
60 return new BigInteger(ba);
61}
62
Axel Colin de Verdieref049a762012-05-19 12:10:17 -070063/**
64 * "empty" RSA key constructor
65 * @returns {RSAKey}
66 */
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070067function RSAKey() {
68 this.n = null;
69 this.e = 0;
70 this.d = null;
71 this.p = null;
72 this.q = null;
73 this.dmp1 = null;
74 this.dmq1 = null;
75 this.coeff = null;
76}
77
Axel Colin de Verdieref049a762012-05-19 12:10:17 -070078/**
79 * Set the public key fields N and e from hex strings
80 * @param N
81 * @param E
82 * @returns {RSASetPublic}
83 */
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070084function RSASetPublic(N,E) {
85 if(N != null && E != null && N.length > 0 && E.length > 0) {
86 this.n = parseBigInt(N,16);
87 this.e = parseInt(E,16);
88 }
89 else
90 alert("Invalid RSA public key");
91}
92
Axel Colin de Verdieref049a762012-05-19 12:10:17 -070093/**
94 * Perform raw public operation on "x": return x^e (mod n)
95 * @param x
96 * @returns x^e (mod n)
97 */
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070098function RSADoPublic(x) {
99 return x.modPowInt(this.e, this.n);
100}
101
Axel Colin de Verdieref049a762012-05-19 12:10:17 -0700102/**
103 * Return the PKCS#1 RSA encryption of "text" as an even-length hex string
104 */
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700105function RSAEncrypt(text) {
106 var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
107 if(m == null) return null;
108 var c = this.doPublic(m);
109 if(c == null) return null;
110 var h = c.toString(16);
111 if((h.length & 1) == 0) return h; else return "0" + h;
112}
113
114// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
115//function RSAEncryptB64(text) {
116// var h = this.encrypt(text);
117// if(h) return hex2b64(h); else return null;
118//}
119
120// protected
121RSAKey.prototype.doPublic = RSADoPublic;
122
123// public
124RSAKey.prototype.setPublic = RSASetPublic;
125RSAKey.prototype.encrypt = RSAEncrypt;
126//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;