mirror of
https://github.com/moparisthebest/mailiverse
synced 2024-11-06 17:35:04 -05:00
146 lines
3.3 KiB
JavaScript
146 lines
3.3 KiB
JavaScript
|
// Depends on jsbn.js and rng.js
|
||
|
|
||
|
// Version 1.1: support utf-8 encoding in pkcs1pad2
|
||
|
|
||
|
// convert a (hex) string to a bignum object
|
||
|
function parseBigInt(str,r) {
|
||
|
return new BigInteger(str,r);
|
||
|
}
|
||
|
|
||
|
function linebrk(s,n) {
|
||
|
var ret = "";
|
||
|
var i = 0;
|
||
|
while(i + n < s.length) {
|
||
|
ret += s.substring(i,i+n) + "\n";
|
||
|
i += n;
|
||
|
}
|
||
|
return ret + s.substring(i,s.length);
|
||
|
}
|
||
|
|
||
|
function byte2Hex(b) {
|
||
|
if(b < 0x10)
|
||
|
return "0" + b.toString(16);
|
||
|
else
|
||
|
return b.toString(16);
|
||
|
}
|
||
|
|
||
|
//PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
|
||
|
function pkcs1pad2(s,n) {
|
||
|
var bia = hextoBA(s);
|
||
|
|
||
|
if(n < bia.length + 11) { // TODO: fix for utf-8
|
||
|
alert("Message too long for RSA");
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
var ba = new Array();
|
||
|
var i = bia.length;
|
||
|
while (i>0 && n>0)
|
||
|
{
|
||
|
ba[--n] = bia[--i];
|
||
|
}
|
||
|
|
||
|
// tjp, what if n == 0? what then
|
||
|
// this will fail
|
||
|
// but I think maximum i'm sending in is 244 or something
|
||
|
ba[--n] = 0;
|
||
|
var rng = new SecureRandom();
|
||
|
var x = new Array();
|
||
|
while(n > 2) { // random non-zero pad
|
||
|
x[0] = 0;
|
||
|
while(x[0] == 0) rng.nextBytes(x);
|
||
|
ba[--n] = x[0];
|
||
|
}
|
||
|
ba[--n] = 2;
|
||
|
ba[--n] = 0;
|
||
|
return new BigInteger(ba);
|
||
|
}
|
||
|
|
||
|
|
||
|
// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
|
||
|
function pkcs1pad2_NO(s,n) {
|
||
|
if(n < s.length + 11) { // TODO: fix for utf-8
|
||
|
alert("Message too long for RSA");
|
||
|
return null;
|
||
|
}
|
||
|
var ba = new Array();
|
||
|
var i = s.length - 1;
|
||
|
while(i >= 0 && n > 0) {
|
||
|
var c = s.charCodeAt(i--);
|
||
|
if(c < 128) { // encode using utf-8
|
||
|
ba[--n] = c;
|
||
|
}
|
||
|
else if((c > 127) && (c < 2048)) {
|
||
|
ba[--n] = (c & 63) | 128;
|
||
|
ba[--n] = (c >> 6) | 192;
|
||
|
}
|
||
|
else {
|
||
|
ba[--n] = (c & 63) | 128;
|
||
|
ba[--n] = ((c >> 6) & 63) | 128;
|
||
|
ba[--n] = (c >> 12) | 224;
|
||
|
}
|
||
|
}
|
||
|
ba[--n] = 0;
|
||
|
var rng = new SecureRandom();
|
||
|
var x = new Array();
|
||
|
while(n > 2) { // random non-zero pad
|
||
|
x[0] = 0;
|
||
|
while(x[0] == 0) rng.nextBytes(x);
|
||
|
ba[--n] = x[0];
|
||
|
}
|
||
|
ba[--n] = 2;
|
||
|
ba[--n] = 0;
|
||
|
return new BigInteger(ba);
|
||
|
}
|
||
|
|
||
|
// "empty" RSA key constructor
|
||
|
function RSAKey() {
|
||
|
this.n = null;
|
||
|
this.e = 0;
|
||
|
this.d = null;
|
||
|
this.p = null;
|
||
|
this.q = null;
|
||
|
this.dmp1 = null;
|
||
|
this.dmq1 = null;
|
||
|
this.coeff = null;
|
||
|
}
|
||
|
|
||
|
// Set the public key fields N and e from hex strings
|
||
|
function RSASetPublic(N,E) {
|
||
|
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
||
|
this.n = parseBigInt(N,16);
|
||
|
this.e = parseInt(E,16);
|
||
|
}
|
||
|
else
|
||
|
alert("Invalid RSA public key");
|
||
|
}
|
||
|
|
||
|
// Perform raw public operation on "x": return x^e (mod n)
|
||
|
function RSADoPublic(x) {
|
||
|
return x.modPowInt(this.e, this.n);
|
||
|
}
|
||
|
|
||
|
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
|
||
|
function RSAEncrypt(text) {
|
||
|
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
|
||
|
if(m == null) return null;
|
||
|
var c = this.doPublic(m);
|
||
|
if(c == null) return null;
|
||
|
var h = c.toString(16);
|
||
|
if((h.length & 1) == 0) return h; else return "0" + h;
|
||
|
}
|
||
|
|
||
|
// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
|
||
|
//function RSAEncryptB64(text) {
|
||
|
// var h = this.encrypt(text);
|
||
|
// if(h) return hex2b64(h); else return null;
|
||
|
//}
|
||
|
|
||
|
// protected
|
||
|
RSAKey.prototype.doPublic = RSADoPublic;
|
||
|
|
||
|
// public
|
||
|
RSAKey.prototype.setPublic = RSASetPublic;
|
||
|
RSAKey.prototype.encrypt = RSAEncrypt;
|
||
|
//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
|