赞
踩
一种被广泛使用的单向哈希算法不可逆,可以产生出一个128位(16字节的散列值
import { createHash } from 'crypto'; //十六进制的字符串形式 static hexDigits: string[] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', ]; //md5加密方式 static encodeByMD5(originString: string): string { if (originString) { try { //创建实例,指定md5为哈希加密方式 const hash = createHash('md5'); //返回值为buffer类型的字节数组(第一个值为要加密的字符串,第二个规定为utf8形式) const results = hash.update(originString, 'utf8').digest(); //调用方法将字节数组转为字符串 const resultString: string = this.byteArrayToHexString(results); return resultString; } catch (ex) { console.error(ex); } } return ''; } //接收一个buffer类型的字节数组,返回值为string类型 static byteArrayToHexString(b: Buffer): string { let resultSb = ''; //for循环遍历字节数组 for (let i = 0; i < b.length; i++) { //调用方法进行转换 resultSb += this.byteToHexString(b[i]); } return resultSb; } static byteToHexString(b: number): string { //先对数字进行了处理,如果它是一个负数,则将其调整为一个无符号的 8 位整数(因为 JavaScript 中的数字是以 IEEE 754 格式的浮点数来存储的,所以需要显式地转成 8 位整数)。然后,分别计算该数的个位和十位上的十六进制值,将其转换为对应的字符,拼接起来成为一个 2 位的十六进制字符串返回。 let n: number = b; if (n < 0) { n = 256 + n; } const d1 = n / 16; //个位十六进制值 const d2 = n % 16; //十位十六进制值 //转为整数类型 const d3 = parseInt(d1.toString()); const d4 = parseInt(d2.toString()); //两位十六进制字符串 return this.hexDigits[d3] + this.hexDigits[d4]; }
static md5(source: string): string {
const hash = createHash('md5');
hash.update(source, 'utf8');
return hash.digest('hex');//上面的实现可以通过传递一个hex直接实现
}
下载依赖:
npm install crypto-js
import * as CryptoJS from 'crypto-js'; static md5(source:string){ //md5加密 const wordArray = CryptoJS.enc.Utf8.parse('2022JueJin') CryptoJS.MD5(wordArray).toString(); //base64 const base64 = CryptoJS.enc.Base64.stringify(CryptoJS.MD5('2022JueJin')) const base64two = Buffer.from(source).toString('base64'), //第一种加密出来是只有base64加密 //第二种多加了一层url加密 } //url加密实现原理 static urlEncode(str: string): string { let encodedStr = encodeURIComponent(str); encodedStr = encodedStr.replace(/[-_.!~*'()]/g, (char) => { const hexCode = char.charCodeAt(0).toString(16).toUpperCase(); return `%${hexCode}`; }); return encodedStr; }
这里只做简单的介绍,有兴趣可以深入了解.
哈希法又称为:散列法,杂凑法,关键字地址计算法,相对应的表称为哈希表,散列表或杂凑表.
基本思想:首先在元素的关键字k和元素的存储位置p之间简历一个对应关系H,使得p=H(k),H称为焊锡函数,创建哈希表时,把关键字为k的元素直接存入地址为H(k)的单元.查找时候利用哈希函数计算出位置.
数字分析法,平方取中法,分段叠加法,除留余数法,伪随机数法
开放定址法,再哈希法,链地址法,建立公共溢出区
已知一组关键字序列(19,14,23 ,01 ,68 ,20,84 ,27,55,11,10,79),给出按哈希函数H(key)=key%13和线性探测处理冲突构造所得哈希表ht[0…15]。
如图所示。其中,每个关键字下面带圈的数字,是放置该关键字时所进行的地址计算次数,或者说是放置该关键字时所进行的关键字比较次数(同时也是查找该关键字时所进行的关键字比较次数)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgbeNhEZ-1681466387252)(C:\Users\57429\AppData\Roaming\Typora\typora-user-images\1681380409994.png)]
查找19时,通过计算H(19)= 6,ht[6]. key非空且值为19查找成功则查我关键字19,仅需要计算一次地址就可以找到。 在找14时,通过计算H(14)=1,ht[1],key非空且值为14查找成功,查找 23时,通过计算H(23)= 10,ht[ 10]. key非空且值为23查找成功,则查找关键字23.仅需要计算一次地址就可以找到。同样,查找关键字68 ,20,11 ,均需要计算一次地址就可以找到。
查找关键字01时,通过计算H(01)= 1,ht[1].key非空且值为14≠01,则找第一次冲突处理后的地址h=(1+1)% 16=2,此时,ht[2]. key非空且值为01,查找成功,因此查找关键字01时,需要计算二次地址才可以找到。
查找关键字55时,通过计算H(55)=3,h[3. key非空且值为68≠55,则找第一次冲突处 h=(3+1)%16=4.此时,ht[4].key非空且值为27≠55,则查找两次冲突后处理地址为h2=(3+2)%16=5,ht[5].key非空且值为55,查找成功,因此查找55,需要计算三次.
AES为高级加密标准(Advanced Encryption Standard,AES),是一种对称加密算法,根据加密算法不同,密钥的长度和IV的长度不同,aes-128-cbc,那么cipher文件中的key和iv必须为16字节,aes-192-cbc key和iv必须为24字节,aes-256-cbc key和iv必须为32字节。
import * as CryptoJS from 'crypto-js';
const message = CryptoJS.enc.Utf8.parse('JueJin2022')
const secretPassphrase = CryptoJS.enc.Utf8.parse('0123456789asdfgh')
const iv = CryptoJS.enc.Utf8.parse('0123456789asdfgh')
const encrypted = CryptoJS.AES.encrypt(message, secretPassphrase, {
mode: CryptoJS.mode.CBC,
paddding: CryptoJS.pad.Pkcs7,
iv
}).toString()
console.log(encrypted)
使用aes-128-cbc加密和解密字符串123456,密钥为:nnnnnnnnnnnnnnnn
let a2 = require("crypto"); //aes128加密 function aes128encrypt(data, key){ let t1 = a2.createCipheriv('aes-128-cbc',key, "nnnnnnnnnnnnnnnn"); let crypted = t1.update(data,'utf-8','hex'); crypted += t1.final('hex'); return crypted; } //aes128解密 function unaes256encrypt(crypted,key){ let t2 = a2.createDecipheriv('aes-128-cbc', key, "nnnnnnnnnnnnnnnn"); let decrypted = t2.update(crypted, 'hex', 'utf8'); decrypted += t2.final('utf8'); return decrypted; } 输出结果为123456 console.log(unaes256encrypt(aes256encrypt("123456","nnnnnnnnnnnnnnnn"),"nnnnnnnnnnnnnnnn"));
CryptoJS.AES.encrypt()
可以传入 3 个参数: 第 1 个为需要加密的明文; 第 2 个是秘钥,长度可以是 128、192 或 256 bit; 第 3 个为一个配置对象,可以添加一些配置。常见的配置属性有:
注意,明文、秘钥和偏移向量一般先用诸如 CryptoJS.enc.Utf8.parse()
转成 WordArray 对象再传入,这样做得到结果与不转换直接传入是不一样的。
RSA 是一种非对称加密算法,使用公钥(公开密钥PK)加密、私钥(秘密密钥SK)解密;
import * as crypto from 'crypto'; export class RSA { private _privateKey: string; private _publicKey: string; private keySize: number; constructor(keySize: number) { //RSA允许你选择公钥的大小。512位的密钥被视为不安全的;768位的密钥不用担心受到除了国家安全管理(NSA)外 的其他事物的危害 this.keySize = keySize || 1024; //从 node.js 的 v10.12.0 开始,可以使用内部模块 crypto.generateKeyPairSync 方法生成公私钥 const keyPair = crypto.generateKeyPairSync('rsa', { modulusLength: this.keySize, //配置加密参数(填充方式,加密模式等) publicKeyEncoding: { type: 'spki', format: 'pem', }, privateKeyEncoding: { type: 'pkcs8', format: 'pem', }, }); this._privateKey = keyPair.privateKey; this._publicKey = keyPair.publicKey; } // 设置 privateKey 的 setter 方法 set privateKey(privateKey: string) { this._privateKey = privateKey; } // 设置 publicKey 的 setter 方法 set publicKey(publicKey: string) { this._publicKey = publicKey; } // 获取 privateKey 的 getter 方法 get getPrivateKey(): string { return this._privateKey; } // 获取 publicKey 的 getter 方法 get getPublicKey(): string { return this._publicKey; } // 加密 encrypt(data): string { const buffer = Buffer.from(data, 'utf-8'); const encryptedBuffer = crypto.publicEncrypt(this._publicKey, buffer); return encryptedBuffer.toString('base64'); } // 解密 decrypt(data): string { const buffer = Buffer.from(data, 'base64'); const decryptedBuffer = crypto.privateDecrypt(this._privateKey, buffer); return decryptedBuffer.toString('utf-8'); } } 该示例中,定义了一个 RSA 类,通过 crypto 模块来实现 RSA 加密算法。构造函数中,设置了加密密钥的长度,同时使用 crypto.generateKeyPairSync() 方法来生成公钥和私钥。其中,modulusLength 参数表示密钥的长度,publicKeyEncoding 和 privateKeyEncoding 分别表示公钥和私钥的格式。 在 encrypt 方法中,将输入的字符串转换为 Buffer 对象,并使用 crypto.publicEncrypt() 方法进行加密,传入公钥进行加密。最后将加密后的结果转换为指定编码方式的字符串并返回。 在 decrypt 方法中,先将输入的字符串转换为 Buffer 对象,然后使用 crypto.privateDecrypt() 方法进行解密,传入私钥进行解密。最后将解密后的结果转换为指定编码方式的字符串并返回。 需要注意的是,加密和解密使用的是不同的公钥和私钥。在使用时,需要新建一个 RSA 实例,并将其公钥用于加密,私钥用于解密。同时也需要注意密钥的保密性,确保密钥不会泄露。 //使用方法 async Rsa(req) { const rsa = new RSA(1024); console.log(rsa, 'rsa1'); const pub = rsa.getPublicKey; const pri = rsa.getPrivateKey; console.log(pub, 'pub'); console.log(pri, 'pri'); rsa.privateKey = 'pri'; rsa.publicKey = 'pub'; console.log(rsa, 'rsa2'); //加密 const b = rsa.encrypt('1234'); //解密 const a = rsa.decrypt(b); return { a, b }; } //以上封装的类RSA基本上就是node-rsa的实现原理,传参方面略有不同,更深层次可以查看源码.
node-rsa
npm install node-rsa
import * as RSA from 'node-rsa';
import * as crypto from 'crypto';
//如果不指定导出格式,公钥默认是pkcs8,私钥是pkcs1
const key = new NodeRSA({b: 512});//生成512位秘钥
let pubkey = key.exportKey('pkcs8-public');//导出公钥
let prikey = key.exportKey('pkcs8-private');//导出私钥
//生成两个实例
let pubKey = new NodeRSA(pubKey,'pkcs8-public');//导入公钥
let priKey = new NodeRSA(priKey,'pkcs8-private');//导入私钥
// --- RSA ---
// rsa加密
static rsaEncode(code: string) {
const privateRSA = new RSA(Encrypt.RSA.PRIVATE_KEY);
return privateRSA.encrypt(code, 'base64');
}
// rsa解密
static rsaDecode(code: string) {
const privateRSA = new RSA(Encrypt.RSA.PRIVATE_KEY);
return privateRSA.decrypt(code, 'utf8');
}
看到了一个很好的C/S的设计思路:
SHA256是安全散列算法(Secure Hash Algorithm),对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,长度为32个字节,通常用一个长度为64的十六进制字符串来表示
let a1 = require("crypto-js");
let a2 = require("crypto");
let res3 = a1.SHA256("123456").toString();
let res4 = a2.createHash("sha256").update("123456").digest('hex');
//使用res3或res4都可以,加密结果一样
console.log(res3);
console.log(res4);
let a1 = require("crypto-js");
let a2 = require("crypto");
let res5 = a1.HmacMD5("123456", "apple").toString();
let res6 = a2.createHmac("md5","apple").update("123456").digest('hex');
//使用res5或res6都可以,加密结果一样
console.log(res5);
console.log(res6);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。