const crypto = require('crypto')
const { createHash } = require('crypto');
const nodeRSA = require('node-rsa');
const FOFencrypt = (algorithm, content) => {
	let hash = createHash(algorithm)
	hash.update(content)
	return hash.digest('hex')
}
//常用哈希加密
exports.md5 = str => {
	return FOFencrypt("md5", str)
}
exports.md5hmac = (str, password) => {
	const hmac = crypto.createHmac('md5', password);
	// 往hmac对象中添加摘要内容
	const up = hmac.update(str);
	// 使用 digest 方法输出摘要内容
	const result = up.digest('hex');
	return result;
};
exports.sha1 = (str) => {
	return FOFencrypt("sha1", str)
}
exports.sha256 = (str) => {
	return FOFencrypt("sha256", str)
}
exports.shaSet = (code, str) => {
	return FOFencrypt(code, str)
}
exports.shaSethmac = (code, str, salt) => {
	const hmac = crypto.createHmac(code, salt);
	// 往hmac对象中添加摘要内容
	const up = hmac.update(str);
	// 使用 digest 方法输出摘要内容
	const result = up.digest('hex');
	return result;
}
exports.sha256hmac = (str, salt) => {
	const hmac = crypto.createHmac('sha256', salt);
	// 往hmac对象中添加摘要内容
	const up = hmac.update(str);
	// 使用 digest 方法输出摘要内容
	const result = up.digest('hex');
	return result;
}

/**
 * Base64加解密
 */
exports.encryptBase64 = str => {
	return Buffer.from(str, 'utf-8').toString('base64')
}
exports.decryptBase64 = str => {
	return Buffer.from(str, 'base64').toString('utf8')
}

/**
 * DES加解密
 * key加密密钥 8位
 * iv初始化向量 8位
 * 'des-ecb'/'des-cbc'
 */
exports.encryptDes = (str, key, iv = null, destype = 'des-ecb') => {
	if (iv == null) {
		iv = key;
	}
	if (destype == 'des-ecb') {
		iv = null;
	}
	const cipher = crypto.createCipheriv(destype, key, iv);
	let encrypted = cipher.update(str, 'utf8', 'hex');
	encrypted += cipher.final('hex');
	return encrypted
}
exports.decryptDes = (str, key, iv = null, destype = 'des-ecb') => {
	if (iv == null) {
		iv = key;
	}
	if (destype == 'des-ecb') {
		iv = null;
	}
	const cipher = crypto.createDecipheriv(destype, key, iv)
	var crypted = cipher.update(str, 'hex', 'utf8')
	crypted += cipher.final('utf8')
	return crypted
}

/**
 * AES加解密
 * key加密密钥 aes128-16位，aes192-24位，aes256-32位
 * iv初始化向量 null或16位
 * 'aes-128-ecb'/'aes-128-cbc'
 */
exports.encryptAes = (str, key, iv = null, destype = 'aes-128-ecb') => {
	if (iv == null) {
		iv = key;
	}
	if (destype.indexOf('ecb') != -1) {
		iv = null;
	}
	let sign = '';
	const cipher = crypto.createCipheriv(destype, key, iv);
	sign += cipher.update(str, 'utf8', 'hex');
	sign += cipher.final('hex');
	return sign;
}
exports.decryptAes = (str, key, iv = null, destype = 'aes-128-ecb') => {
	if (iv == null) {
		iv = key;
	}
	if (destype.indexOf('ecb') != -1) {
		iv = null;
	}
	const cipher = crypto.createDecipheriv(destype, key, iv)
	var crypted = cipher.update(str, 'hex', 'utf8')
	crypted += cipher.final('utf8')
	return crypted
}

/**
 * RSA加解密
 */
exports.generateRSAKey = (size = 1024) => {
	const key = new nodeRSA({ b: size })
	const publicKey = key.exportKey('public')
	const privateKey = key.exportKey('private')
	return { '公钥': publicKey, '私钥': privateKey }
}
// 私钥加密 公钥解密
exports.encryptRSAByPrivateKey = (str, privateKey) => {
	let key = null;
	if (typeof privateKey === "string") {
		key = new nodeRSA(privateKey, {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'private', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		});
	} else {
		let keyObj = {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'private', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		}
		if (privateKey["位数"]) {
			keyObj["b"] = privateKey["位数"]
		}
		if (privateKey["密钥类型"]) {
			keyObj["k"] = privateKey["密钥类型"]
		}
		if (privateKey["填充方式"]) {
			keyObj["scheme"] = privateKey["填充方式"]
		}
		if (privateKey["哈希函数"]) {
			keyObj["hash"] = privateKey["哈希函数"]
		}
		keyObj["scheme"] = keyObj["scheme"].toLowerCase()
		if (keyObj["scheme"] != "oaep") {
			key = new nodeRSA(privateKey["密钥"], keyObj);
			key.setOptions({ encryptionScheme: keyObj["scheme"] });
		} else {
			key = new nodeRSA(privateKey["密钥"], keyObj);
		}
	}
	return key.encryptPrivate(str, 'base64')
}
exports.decryptRSAByPublicKey = (str, publicKey) => {
	let key = null;
	if (typeof publicKey === "string") {
		key = new nodeRSA(publicKey, {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'public', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		});
	} else {
		let keyObj = {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'public', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		}
		if (publicKey["位数"]) {
			keyObj["b"] = publicKey["位数"]
		}
		if (publicKey["密钥类型"]) {
			keyObj["k"] = publicKey["密钥类型"]
		}
		if (publicKey["填充方式"]) {
			keyObj["scheme"] = publicKey["填充方式"]
		}
		if (publicKey["哈希函数"]) {
			keyObj["hash"] = publicKey["哈希函数"]
		}
		keyObj["scheme"] = keyObj["scheme"].toLowerCase()
		if (keyObj["scheme"] != "oaep") {
			key = new nodeRSA(publicKey["密钥"], keyObj);
			key.setOptions({ encryptionScheme: keyObj["scheme"] });
		} else {
			key = new nodeRSA(publicKey["密钥"], keyObj);
		}
	}
	return key.decryptPublic(str, 'utf-8')
}
// 公钥加密 私钥解密
exports.encryptRSAByPublicKey = (str, public) => {
	let key = null;
	if (typeof public === "string") {
		key = new nodeRSA(public, {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'private', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		});
	} else {
		let keyObj = {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'private', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		}
		if (public["位数"]) {
			keyObj["b"] = public["位数"]
		}
		if (public["密钥类型"]) {
			keyObj["k"] = public["密钥类型"]
		}
		if (public["填充方式"]) {
			keyObj["scheme"] = public["填充方式"]
		}
		if (public["哈希函数"]) {
			keyObj["hash"] = public["哈希函数"]
		}
		keyObj["scheme"] = keyObj["scheme"].toLowerCase()
		if (keyObj["scheme"] != "oaep") {
			key = new nodeRSA(public["密钥"], keyObj);
			key.setOptions({ encryptionScheme: keyObj["scheme"] });
		} else {
			key = new nodeRSA(public["密钥"], keyObj);
		}
	}
	return key.encrypt(str, 'base64')
}
exports.decryptRSAByPrivateKey = (str, PrivateKey) => {
	let key = null;
	if (typeof PrivateKey === "string") {
		key = new nodeRSA(PrivateKey, {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'private', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		});
	} else {
		let keyObj = {
			b: 1024, // 指定密钥大小（位数），如果私钥已经给出，则此选项将被忽略  
			k: 'private', // 指定密钥类型（'private' 或 'public'），如果私钥字符串被给出，则默认为 'private'  
			scheme: 'oaep', // 设置填充方式为 OAEP  
			hash: 'sha256' // 设置哈希函数为 SHA-256  
		}
		if (PrivateKey["位数"]) {
			keyObj["b"] = PrivateKey["位数"]
		}
		if (PrivateKey["密钥类型"]) {
			keyObj["k"] = PrivateKey["密钥类型"]
		}
		if (PrivateKey["填充方式"]) {
			keyObj["scheme"] = PrivateKey["填充方式"]
		}
		if (PrivateKey["哈希函数"]) {
			keyObj["hash"] = PrivateKey["哈希函数"]
		}
		keyObj["scheme"] = keyObj["scheme"].toLowerCase()
		if (keyObj["scheme"] != "oaep") {
			key = new nodeRSA(PrivateKey["密钥"], keyObj);
			key.setOptions({ encryptionScheme: keyObj["scheme"] });
		} else {
			key = new nodeRSA(PrivateKey["密钥"], keyObj);
		}
	}
	return key.decrypt(str, 'utf-8')
}