使用jsencrypt.js实现RSA加密和解密(长消息版)

<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>使用jsencrypt.js实现RSA加密和解密</title>
</head>
<body>
<script type="text/javascript" src="./jsencrypt.min.js"></script> 
<script type="text/javascript">    
JSEncrypt.prototype.hexToB64 = function(h) {
   var b64map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
   var i;
   var c;
   var ret = '';

   for (i = 0; i + 3 <= h.length; i += 3) {
      c = parseInt(h.substring(i, i + 3), 16);
      ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
   }

   if (i + 1 == h.length) {
      c = parseInt(h.substring(i, i + 1), 16);
      ret += b64map.charAt(c << 2);
   } else if (i + 2 == h.length) {
      c = parseInt(h.substring(i, i + 2), 16);
      ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
   }

   while ((ret.length & 3) > 0) {
      ret += '=';
   }

   return ret;
};

JSEncrypt.prototype.b64ToHex = function(s) {
   var b64map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
   var ret = '';
   var i;
   var k = 0;
   var slop = 0;

   let intToChar = function(n) {
      return '0123456789abcdefghijklmnopqrstuvwxyz'.charAt(n);
   }

   for (i = 0; i < s.length; ++i) {
      if (s.charAt(i) == '=') {
         break;
      }

      var v = b64map.indexOf(s.charAt(i));
      if (v < 0) {
         continue;
      }

      if (k == 0) {
         ret += intToChar(v >> 2);
         slop = v & 3;
         k = 1;
      } else if (k == 1) {
         ret += intToChar((slop << 2) | (v >> 4));
         slop = v & 0xf;
         k = 2;
      } else if (k == 2) {
         ret += intToChar(slop);
         ret += intToChar(v >> 2);
         slop = v & 3;
         k = 3;
      } else {
         ret += intToChar((slop << 2) | (v >> 4));
         ret += intToChar(v & 0xf);
         k = 0;
      }
   }

   if (k == 1) {
      ret += intToChar(slop << 2);
   }

   return ret;
}

JSEncrypt.prototype.encryptUnicodeLong = function(string) {
   var k = this.getKey();
   var maxLength = ((k.n.bitLength() + 7) >> 3) - 11; // 明文允许的最大长度

   try {
      var subStr = '';
      var encryptedString = '';
      var subStart = 0;
      var subEnd = 0;
      var bitLen = 0;
      var tmpPoint = 0;

      for (var i = 0, len = string.length; i < len; i++) {
         var charCode = string.charCodeAt(i);

         if (charCode <= 0x007f) { // 单字节
            bitLen += 1;
         } else if (charCode <= 0x07ff) { // 双字节
            bitLen += 2;
         } else if (charCode <= 0xffff) { // 三字节
            bitLen += 3;
         } else {
            bitLen += 4;
         }

         if (bitLen > maxLength) {
            subStr = string.substring(subStart, subEnd)
            encryptedString += k.encrypt(subStr);
            subStart = subEnd;
            bitLen = bitLen - tmpPoint;
         } else {
            subEnd = i;
            tmpPoint = bitLen;
         }
      }

      subStr = string.substring(subStart, len)
      encryptedString += k.encrypt(subStr);

      return this.hexToB64(encryptedString);
   } catch (ex) {
      return false;
   }
};

JSEncrypt.prototype.decryptUnicodeLong = function(string) {
   var k = this.getKey();
   var maxLength = ((k.n.bitLength() + 7) >> 3) * 2;

   try {
      var hexString = this.b64ToHex(string);
      var decryptedString = '';
      var rexStr = '.{1,' + maxLength + '}';
      var rex = new RegExp(rexStr, 'g');
      var subStrArray = hexString.match(rex);

      if (subStrArray) {
         subStrArray.forEach(function(entry) {
            decryptedString += k.decrypt(entry);
         });

         return decryptedString;
      }
   } catch (ex) {
      return false;
   }
};





//========== 公钥 ==========//
var publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzjGQT86U567mS2j3dzuf
Q6sDJJDGfnO9J8ESaiwvMChZ30zD/USypRlKSnX1d+bqTLFMoNEOK/bQmqZiiSk5
Fzek2IA78n4NsvorKfsc5Gje2RQGqG5kKMt1TfLg2cF8dOZ+8Q6FoJ6EB3Dd1KPU
f0duLcEXs+Am70CVeBs7aGYVUY2dtVlAVSK1mlUmYWNxRlk5V5oSdUaHN9vAzgiJ
Y844bbpP3XOCgT/Fc0sN+AVoGIrgAyGt1qWHTiXIbJQ0ocyFoaT/CCdP7ueqesJp
LCxupSqoS0SdNh3JpbLz4ZnHGug7uP1mqwkGQACAJfYE6X7fNRO+BIaVJRGCMBcm
jwIDAQAB
-----END PUBLIC KEY-----`;

//========== 私钥 ==========//
var privateKey = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDOMZBPzpTnruZL
aPd3O59DqwMkkMZ+c70nwRJqLC8wKFnfTMP9RLKlGUpKdfV35upMsUyg0Q4r9tCa
pmKJKTkXN6TYgDvyfg2y+isp+xzkaN7ZFAaobmQoy3VN8uDZwXx05n7xDoWgnoQH
cN3Uo9R/R24twRez4CbvQJV4GztoZhVRjZ21WUBVIrWaVSZhY3FGWTlXmhJ1Roc3
28DOCIljzjhtuk/dc4KBP8VzSw34BWgYiuADIa3WpYdOJchslDShzIWhpP8IJ0/u
56p6wmksLG6lKqhLRJ02HcmlsvPhmcca6Du4/WarCQZAAIAl9gTpft81E74EhpUl
EYIwFyaPAgMBAAECggEAR5X7lUmSdvFI8QtrRxEDFTotKCe/Ui2akU+9tfDLHTwV
H6qGLMsJ/rnOChXz+AHKfH/dq8OI2Qiimd6EPTx7nqzp5WR365OJ7AZgr/2HpWEn
ZVRHj3hr+6HPgxV8rP042Vkg3038ZKxECFVOHsIWR24kOWxdb0y2F8BjZESIFpEi
IRN9Xb77C2yCOUX/yoyMgjkKM/Z+cThM5wQ0nR1wZHDl4CE91UxhdDYBQz5uzoDV
qZerHT2Kmy5fUBRGxJdSujN7qyGgf9FarNkfBYAII97StIS512ZuLCwzmEddXp4i
gNlsla0eqCxQvAqOoGm8Fp/N0PCyfR7fJexck3L1kQKBgQD+SvKklvp055BpVB2n
IsJHpPd43zXxxX+k8eQSKhGIy+6eO53xapQDZiB/4OVfGnY+xPF4z8nLxCWd9C3S
K6X/OzQTC7c4Y4a9L/P2NKissuqsxzMf2jGPCUBIGKcBZ9eizOGNbdhJ/HvXQY7r
CxyRaeOqU6om1DKPHBkFsXPfGQKBgQDPk/Kxugnzgv+4b2TWwxY7Ot2LcWszPkEp
RsbBLdCS08h9GYOlC1kGMXZFv8QGO3R+e4mZMOIVhwSadrhfGwvlqDumDaORF+MH
ZZAe6ARRX71KKTjGZqcX0nImLI5o1s/YMK8BkCE6ArYVPFspk68Voun4wbNcO/U9
aoNsK9Vv5wKBgQDDW3jFkWegYDXFdWXCfSWcPNQR/AlJUF0brul0OvV1jpYm4c4Z
JbPIWLEnDPOp+H5XAp4wHhH9hRcRHgIFsJq6VhVPfHSp0Ww1850MzK+43UsEqZRR
KCNiq8zClo3Wupwi6httt7GuRVYurKLLV6H+5MaOl+/kHKkq4H8orIdEIQKBgGng
uOXWUsUWiID2sKSqlWhYujAqBdf5ZRs8spxOVhjOVXEZ1oAUra/vArjI+5+CLAVn
1eOBf5AjckGnVJuOHB9kFCi6xDd5y582OrDI/4rSHqb5J7BrI8eO3BKEn47yIsnO
6zUM4yXHxEBIrOckISYUFut/QZFGM+zDq409Pnz5AoGAXqkbybLPznaumBngpY25
BOnBxF02hWxiWlREsXbqfpa6WU50BLXFxknP+91QYwOHafZpdjm7LL8GJ7H5vmyK
CLhxY5fZejlze0eMa8A07JWBH9F4cBamI9NbmatfmhlvLjPaRcNaoyuk1W8LuL9Z
im+u/8E9Zm1atbpr7lP33YQ=
-----END PRIVATE KEY-----`;





// 要加密的消息
var message = '北国风光,千里冰封,万里雪飘。望长城内外,惟余莽莽;大河上下,顿失滔滔。山舞银蛇,原驰蜡象,欲与天公试比高。须晴日,看红装素裹,分外妖娆。江山如此多娇,引无数英雄竞折腰。惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。一代天骄,成吉思汗,只识弯弓射大雕。俱往矣,数风流人物,还看今朝。';

var jse = new JSEncrypt();

//========== 使用公钥加密 ==========//
jse.setKey(publicKey);
var ciphertext = jse.encryptUnicodeLong(message); // 注:相同消息每次加密的结果都是不同的
console.log('密文:' + ciphertext); // 密文:jWMTTKptcjW0llb25eWEaTlBoz08OFAlhL8EZ79S0IguMtWCjWqVgIKMwiPhuUyqDfpk5g8VatV6T7d7……

//========== 使用私钥解密 ==========//
jse.setKey(privateKey);
var plaintext = jse.decryptUnicodeLong(ciphertext);
console.log('明文:' + plaintext); // 明文:北国风光,千里冰封,万里雪飘。望长城内外,惟余莽莽;大河上下,顿失滔滔。山舞银蛇,……
</script>
</body>
</html>

Copyright © 2023 码农人生. All Rights Reserved