| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- import { hmacSha256 } from "./encrypt/hmacSha256"
- import * as CryptoJS from "./encrypt/aes.js"
- /**
- * 加密解密工具类
- * @author 邹勇
- */
- export class EncryptUtil {
- /**
- * 随机生成多位字符串
- * @param len 字符串长度
- * @returns
- */
- public randomString(len = 32) {
- let $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnoprstuvwxyz123456789';
- let maxPos = $chars.length;
- let pwd = '';
- for (let i = 0; i < len; i++) {
- pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
- }
- return pwd;
- }
- //说明:
- // 1.如果加密解密涉及到前端和后端,则这里的key要保持和后端的key一致
- // 2.AES的算法模式有好几种(ECB,CBC,CFB,OFB),所以也要和后端保持一致
- // 3.AES的补码方式有两种(PKS5,PKS7),所以也要和后端保持一致
- // 4.AES的密钥长度有三种(128,192,256,默认是128),所以也要和后端保持一致
- // 5.AES的加密结果编码方式有两种(base64和十六进制),具体怎么选择由自己定,但是加密和解密的编码方式要统一
- //十六位十六进制数作为秘钥
- // private public key = fun_aes.CryptoJS.enc.Utf8.parse("3454345434543454");
- //十六位十六进制数作为秘钥偏移量
- // private public iv = fun_aes.CryptoJS.enc.Utf8.parse('6666666666666666');
- /**
- * 说明:
- * 1.如果加密解密涉及到前端和后端,则这里的key要保持和后端的key一致
- * 2.AES的算法模式有好几种(ECB,CBC,CFB,OFB),所以也要和后端保持一致
- * 3.AES的补码方式有两种(PKS5,PKS7),所以也要和后端保持一致
- * 4.AES的密钥长度有三种(128,192,256,默认是128),所以也要和后端保持一致
- * 5.AES的加密结果编码方式有两种(base64和十六进制),具体怎么选择由自己定,但是加密和解密的编码方式要统一
- * 十六位十六进制数作为秘钥
- * private public key = fun_aes.CryptoJS.enc.Utf8.parse("3454345434543454");
- * 十六位十六进制数作为秘钥偏移量
- * private public iv = fun_aes.CryptoJS.enc.Utf8.parse('6666666666666666');
- *
- * aes加密
- * @param word 需要加密的字符串
- * @param tkey !!!加密key,32位字符串,一般为sessionkey
- * @param appid 游戏的appid
- * @param state true 存包长 false /r/n
- * @returns
- */
- public encrypt(word, tkey, appid, state = true) {
- let tiv = tkey.substr(0, 16);
- //明文拼接
- let newStr = '';
- if (state) {
- newStr = tiv + word + appid;
- }
- else {
- newStr = tiv + word + '\r\n' + appid;
- }
- //加密后
- let key = CryptoJS.enc.Utf8.parse(tkey);
- let iv = CryptoJS.enc.Utf8.parse(tiv);
- newStr = CryptoJS.enc.Utf8.parse(newStr);
- let encrypted = CryptoJS.AES.encrypt(newStr, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
- encrypted = encrypted.toString();
- let mac = hmacSha256.Instance.hex_hmac_sha256(tkey, encrypted);
- return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(tiv + encrypted + mac));
- }
- /**
- * aes解密
- * @param word 需要加密的字符串
- * @param tkey 加密key,一般为sessionkey
- * @param appid 游戏的appid
- * @param state true 存包长 false /r/n
- * @returns
- */
- public decrypt(word, tkey, appid, state = true) {
- let en = CryptoJS.enc.Base64.parse(word).toString(CryptoJS.enc.Utf8);
- let newStrOne = en.substr(16);
- let temp = newStrOne.substr(0, newStrOne.length - 64);
- let de = temp;
- let key = CryptoJS.enc.Utf8.parse(tkey);
- let iv = CryptoJS.enc.Utf8.parse(tkey.substr(0, 16));
- let decrypt = CryptoJS.AES.decrypt(de, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
- let decryptedStr = CryptoJS.enc.Utf8.stringify(decrypt);
- decryptedStr = decryptedStr.toString();
- let newStrThree = '';
- if (state) {
- newStrThree = decryptedStr.slice(16).replace(new RegExp("(.*)" + appid), '$1');
- }
- else {
- newStrThree = decryptedStr.slice(16).split('\r\n')[0];
- }
- return newStrThree;
- }
- private options = {
- default_key_size: 2048,
- default_public_exponent: new Uint8Array([0x01, 0x00, 0x01])
- }
- /**
- * rsa加密
- * @param word 需要加密的字符串
- * @param isLong 字符串加长版
- * @returns
- */
- public rsaEncrypt(word, isLong: boolean = false) {
- let jsb = new window['JSEncrypt'](this.options);
- //公钥
- let publicString = '-----BEGIN PUBLIC KEY-----\n' +
- 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwz5V8wt525dMS+A9wOd\n' +
- 'NAjvKgxdyoXYuZSlAJEXLhvJlaXwFCKEsUg/qBBeo4nrRnwaFAjG7ItqbCWR9Ozv\n' +
- '6oY5tMYQnFFK82XkMGbKm1gG0z9vYKhcNYgHZHi+QKAw4tLLWXWO/QBTGelEXptD\n' +
- 'azlNmdM+8wHOknTcMuIyjc9Yo5qCoNsCJpA465vnREiBezBbKB3rSw+LmrRcZcFk\n' +
- 's8hmGtjpabcQ8sCxco7mRzVh6/DomNWfNm7hUP6shrrJirwjQtaS51grlScj8KhN\n' +
- 'h+kBoiI4Ad0Xz0GHasK5hAMf3sXDsN61r0An8KTfa/nsYSJDwogPIKkeKAsmw9Df\n' +
- 'EQIDAQAB\n' +
- '-----END PUBLIC KEY-----'
- jsb.setPublicKey(publicString);
- // 加密内容
- let encrypted = isLong ? jsb.encryptLong(word) : jsb.encrypt(word);
- return encrypted;
- }
- /**
- * for php pack( N , length )
- * @param len
- * @returns
- */
- public pack(len: number) {
- let buf: ArrayBuffer = new ArrayBuffer(4);
- let dataView = new DataView(buf);
- dataView.setUint32(0, len);
- let str2 = this.ab2str(buf);
- return str2;
- }
- /**
- *
- * @param array
- * @returns
- */
- public utf8ArrayToStr(array) {
- let out, i, len, c;
- let char2, char3;
- out = "";
- len = array.length;
- i = 0;
- while (i < len) {
- c = array[i++];
- switch (c >> 4) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
- // 0xxxxxxx
- out += String.fromCharCode(c);
- break;
- case 12: case 13:
- // 110x xxxx 10xx xxxx
- char2 = array[i++];
- out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
- break;
- case 14:
- // 1110 xxxx 10xx xxxx 10xx xxxx
- char2 = array[i++];
- char3 = array[i++];
- out += String.fromCharCode(((c & 0x0F) << 12) |
- ((char2 & 0x3F) << 6) |
- ((char3 & 0x3F) << 0));
- break;
- }
- }
- return out;
- }
- /**
- * UTF-16转UTF-8
- * @param s
- * @returns
- */
- public utf16ToUtf8(s) {
- if (!s) {
- return;
- }
- let i, code, ret = [], len = s.length;
- for (i = 0; i < len; i++) {
- code = s.charCodeAt(i);
- if (code > 0x0 && code <= 0x7f) {
- //单字节
- //UTF-16 0000 - 007F
- //UTF-8 0xxxxxxx
- ret.push(s.charAt(i));
- } else if (code >= 0x80 && code <= 0x7ff) {
- //双字节
- //UTF-16 0080 - 07FF
- //UTF-8 110xxxxx 10xxxxxx
- ret.push(
- //110xxxxx
- String.fromCharCode(0xc0 | ((code >> 6) & 0x1f)),
- //10xxxxxx
- String.fromCharCode(0x80 | (code & 0x3f))
- );
- } else if (code >= 0x800 && code <= 0xffff) {
- //三字节
- //UTF-16 0800 - FFFF
- //UTF-8 1110xxxx 10xxxxxx 10xxxxxx
- ret.push(
- //1110xxxx
- String.fromCharCode(0xe0 | ((code >> 12) & 0xf)),
- //10xxxxxx
- String.fromCharCode(0x80 | ((code >> 6) & 0x3f)),
- //10xxxxxx
- String.fromCharCode(0x80 | (code & 0x3f))
- );
- }
- }
- return ret.join('');
- }
- /**
- * UTF-8转UTF-16
- * @param s
- * @returns
- */
- public utf8ToUtf16(s) {
- if (!s) {
- return;
- }
- let i, codes, bytes, ret = [], len = s.length;
- for (i = 0; i < len; i++) {
- codes = [];
- codes.push(s.charCodeAt(i));
- if (((codes[0] >> 7) & 0xff) == 0x0) {
- //单字节 0xxxxxxx
- ret.push(s.charAt(i));
- } else if (((codes[0] >> 5) & 0xff) == 0x6) {
- //双字节 110xxxxx 10xxxxxx
- codes.push(s.charCodeAt(++i));
- bytes = [];
- bytes.push(codes[0] & 0x1f);
- bytes.push(codes[1] & 0x3f);
- ret.push(String.fromCharCode((bytes[0] << 6) | bytes[1]));
- } else if (((codes[0] >> 4) & 0xff) == 0xe) {
- //三字节 1110xxxx 10xxxxxx 10xxxxxx
- codes.push(s.charCodeAt(++i));
- codes.push(s.charCodeAt(++i));
- bytes = [];
- bytes.push((codes[0] << 4) | ((codes[1] >> 2) & 0xf));
- bytes.push(((codes[1] & 0x3) << 6) | (codes[2] & 0x3f));
- ret.push(String.fromCharCode((bytes[0] << 8) | bytes[1]));
- }
- }
- return ret.join('');
- }
- /**
- * ArrayBuffer转为字符串,参数为ArrayBuffer对象
- * @param buf
- * @returns
- */
- public ab2str(buf: ArrayBuffer) {
- return String.fromCharCode.apply(null, new Uint8Array(buf));
- }
- /**
- *
- * @param fileData
- * @returns
- */
- public uint8ArrayToString(fileData) {
- let dataString = "";
- for (let i = 0; i < fileData.length; i++) {
- dataString += String.fromCharCode(fileData[i]);
- }
- return dataString
- }
- /**
- *
- * @param str
- * @returns
- */
- public stringToUint8Array(str) {
- let arr = [];
- for (let i = 0, j = str.length; i < j; ++i) {
- arr.push(str.charCodeAt(i));
- }
- let tmpUint8Array = new Uint8Array(arr);
- return tmpUint8Array
- }
- /**
- * 字符串转为ArrayBuffer对象,参数为字符串
- * @param str
- * @returns
- */
- public str2ab(str) {
- let buf = new ArrayBuffer(str.length); // 每个字符占用2个字节
- let bufView = new Uint8Array(buf);
- for (let i = 0, strLen = str.length; i < strLen; i++) {
- bufView[i] = str.charCodeAt(i);
- }
- return buf;
- }
- }
|