From 2879cf9d50c582c6e24bcfba395d3189d992c081 Mon Sep 17 00:00:00 2001 From: jean-philippe serafin Date: Fri, 17 Jan 2014 14:58:14 +0000 Subject: [PATCH] Add PKCS#1-OAEP padding support for RSA encryption - adapted from @davedoesdev work (http://www.davedoesdev.com/rssssa-pss-and-rsaes-oaep-in-javascript/) --- rsa.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/rsa.js b/rsa.js index 9f86640..5b5d6bd 100644 --- a/rsa.js +++ b/rsa.js @@ -60,6 +60,57 @@ function pkcs1pad2(s,n) { return new BigInteger(ba); } +// PKCS#1 (OAEP) mask generation function +function oaep_mgf1_arr(seed, len) { + var mask = '', i = 0; + + while (mask.length < len) { + mask += rstr_sha1(String.fromCharCode.apply(String, seed.concat([ + (i & 0xff000000) >> 24, + (i & 0x00ff0000) >> 16, + (i & 0x0000ff00) >> 8, + i & 0x000000ff]))); + i += 1; + } + + return mask; +} + +var SHA1_SIZE = 20; + +// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint +function oaep_pad(s, n) { + if (s.length + 2 * SHA1_SIZE + 2 > n) { + alert("Message too long for RSA"); + } + + var PS = '', i; + + for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1) { + PS += '\x00'; + } + + var DB = rstr_sha1('') + PS + '\x01' + s, + seed = new Array(SHA1_SIZE); + new SecureRandom().nextBytes(seed); + + var dbMask = oaep_mgf1_arr(seed, DB.length), + maskedDB = []; + + for (i = 0; i < DB.length; i += 1) { + maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i); + } + + var seedMask = oaep_mgf1_arr(maskedDB, seed.length), + maskedSeed = [0]; + + for (i = 0; i < seed.length; i += 1) { + maskedSeed[i + 1] = seed[i] ^ seedMask.charCodeAt(i); + } + + return new BigInteger(maskedSeed.concat(maskedDB)); +} + // "empty" RSA key constructor function RSAKey() { this.n = null; @@ -88,8 +139,11 @@ function RSADoPublic(x) { } // 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); +function RSAEncrypt(text, paddingFunction) { + if (typeof paddingFunction === typeof undefined) { + paddingFunction = pkcs1pad2; + } + var m = paddingFunction(text,(this.n.bitLength()+7)>>3); if(m == null) return null; var c = this.doPublic(m); if(c == null) return null;