应用场景
一致性验证
MD5 可以为文件传输场景中,提供文件的一致性验证。
例如,文件服务器预先提供一个 MD5 校验值,用户下载完文件以后,用 MD5 算法计算下载文件的 MD5 校验值(如果任何人对文件做了任何改动,这个文件的MD5值就会发生变化),然后通过检查这两个校验值是否一致,就能判断下载的文件是否出错、或者下载的文件是否被篡改了。
现在,利用MD5算法进行文件校验的方法,已经广泛应用到软件下载站、论坛数据库、系统文件安全等方面了。
数字签名
MD5 的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止该段信息被篡改。
例如,在文件“readme.txt”中写入一些内容,并对这个文件进行MD5运算,产生一个MD5值并记录下来,然后可以将这个文件发送给别人,别人如果修改了“readme.txt”文件中的任何内容,我们对这个文件重新计算MD5时,就会发现两个MD5值不同。
在上述过程中,如果再有一个第三方的认证机构介入,那么使用 MD5 还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。
安全访问认证
MD5 还广泛用于操作系统的登录认证中,如 Unix、各类BSD操作系统登录密码、数字签名等诸多方面。
例如,在Unix操作系统中,用户的密码是经MD5(或其它类似的算法)运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5运算,然后再与保存在文件系统中的MD5值进行比较,从而确定用户输入的密码是否正确。通过这些步骤,操作系统在并不知道用户密码的明文的情况下,就可以确定用户登录系统的合法性,这可以避免用户的密码被具有系统管理员权限的用户窃取。
MD5 将任意长度的“字符串”映射为一个128bit的“字符串”,并且通过该128bit的“字符串”反推原始字符串是困难的,换句话说,即使你看到源程序和算法描述,也很难将一个MD5的值转换回原始的字符串。
md5的用途
密码的加密存储,用户设置密码时,服务端只记录这个密码的MD5,而不记录密码本身,以后验证用户身份时,只需要将用户输入的密码再次做一下MD5后,与记录的MD5作一个比较即可验证其密码的合法性。
数字签名,比如发布一个程序,为了防止别人在你的程序里插入病毒或木马,你可以在发布这个程序的同时,公开这个程序文件的MD5码,这样别人只需要在任何地方下载这个程序后做一次MD5,然后跟公开的这个MD5作一个比较就知道这个程序是否被第三方修改过。
文件完整性验证,比如当下载一个文件时,服务器返回的信息中包括这个文件的md5,在本地下载完毕时进行md5,将两个md5值进行比较,如果一致则说明文件完整没有丢包现象。
文件上传,比如百度云实现的秒传,就是对比你上传的文件md5在百度服务器是否已经存在了,如果存在就不用上传了
public class MD5 {
//存储小组
long []groups = null;
//存储结果
String resultMessage="";
//四个寄存器的初始向量IV,采用小端存储
static final long A=0x67452301L;
static final long B=0xefcdab89L;
static final long C=0x98badcfeL;
static final long D=0x10325476L;
//java不支持无符号的基本数据(unsigned),所以选用long数据类型
private long [] result={A,B,C,D};
static final long T[][] = {
{0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821},
{0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a},
{0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665},
{0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}};
//表示X[k]中的的k取值,决定如何使用消息分组中的字
static final int k[][] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
{1, 6,11, 0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12},
{5, 8,11,14, 1, 4, 7,10,13, 0, 3, 6, 9,12,15, 2},
{0, 7,14, 5,12, 3,10, 1, 8,15, 6,13, 4,11, 2, 9}};
//各次迭代中采用的做循环移位的s值
static final int S[][] = {
{7,12,17,22},
{5,9,14,20},
{4,11,16,23},
{6,10,15,21}};
//4轮循环中使用的生成函数(轮函数)g
private static long g(int i, long b, long c, long d) {
switch (i) {
case 0:
return (b & c) | ((~b) & d);
case 1:
return (b & d) | (c & (~d));
case 2:
return b ^ c ^ d;
case 3:
return c ^ (b | (~d));
default:
return 0;
}
}
//开始使用MD5加密
private String start(String message){
//转化为字节数组
byte [] inputBytes=message.getBytes();
//6A 61 6E 6b 69 6e 67
//获取字节数组的长度
int byteLen = inputBytes.length;
//得到K值(以bit作单位的message长度)
long K = (long)(byteLen<<3);
//完整小组(512bit)(64byte)的个数
int groupCount = byteLen/64;
//分块
for(int i = 0;i < groupCount;i++){
//每次取512bit
//处理一个分组
H(divide(inputBytes, i*64));
}
//填充
int rest = byteLen % 64;
//即将填充的一个分组
byte [] paddingBytes=new byte[64];
//原来的尾部数据
for(int i=0;i<rest;i++)
paddingBytes[i]=inputBytes[byteLen-rest+i];
//即小于448bit的情况,先填充100...0再填充K值的低64位
//此时只会新增一个分组
if(rest <= 56){
//填充100...0
if(rest<56){
//填充10000000
paddingBytes[rest]=(byte)(1<<7);
//填充00000000
for(int i=1;i<56-rest;i++)
paddingBytes[rest+i]=0;
}
//填充K值低64位
for(int i=0;i<8;i++){
paddingBytes[56+i]=(byte)(K&0xFFL);
K=K>>8;
}
//处理分组
H(divide(paddingBytes,0));
//即大于448bit的情况,先填充100...0再填充K值的低64位
//此时会新增两个分组
}else{
//填充10000000
paddingBytes[rest]=(byte)(1<<7);
//填充00000000
for(int i=rest+1;i<64;i++)
paddingBytes[i]=0;
//处理第一个尾部分组
H(divide(paddingBytes,0));
//填充00000000
for(int i=0;i<56;i++)
paddingBytes[i]=0;
//填充低64位
for(int i=0;i<8;i++){
//这里很关键,使用小端方式,即Byte数组先存储len的低位数据,然后右移len
paddingBytes[56+i]=(byte)(K&0xFFL);
K=K>>8;
}
//处理第二个尾部分组
H(divide(paddingBytes,0));
}
//将Hash值转换成十六进制的字符串
//小端方式!
for(int i=0;i<4;i++){
resultMessage += Long.toHexString(result[i] & 0xFF) +
Long.toHexString((result[i] & 0xFF00) >> 8) +
Long.toHexString((result[i] & 0xFF0000) >> 16) +
Long.toHexString((result[i] & 0xFF000000) >> 24);
}
return resultMessage;
}
//从inputBytes的index开始取512位,作为新的512bit的分组
private static long[] divide(byte[] inputBytes,int start){
//存储一整个分组,就是512bit,数组里每个是32bit,就是4字节,为了消除符号位的影响,所以使用long
long [] group=new long[16];
for(int i=0;i<16;i++){
//每个32bit由4个字节拼接而来
//小端的从byte数组到bit恢复方法
group[i]=byte2unsign(inputBytes[4*i+start])|
(byte2unsign(inputBytes[4*i+1+start]))<<8|
(byte2unsign(inputBytes[4*i+2+start]))<<16|
(byte2unsign(inputBytes[4*i+3+start]))<<24;
}
return group;
}
//其实byte相当于一个字节的有符号整数,这里不需要符号位,所以把符号位去掉
public static long byte2unsign(byte b){
return b < 0 ? b & 0x7F + 128 : b;
}
// groups[] 中每一个分组512位(64字节)
// MD5压缩函数
private void H(long[] groups) {
//缓冲区(寄存器)数组
long a = result[0], b = result[1], c = result[2], d = result[3];
//四轮循环
for(int n = 0; n < 4; n++) {
//16轮迭代
for(int i = 0; i < 16; i++) {
result[0] += (g(n, result[1], result[2], result[3])&0xFFFFFFFFL) + groups[k[n][i]] + T[n][i];
result[0] = result[1] + ((result[0]&0xFFFFFFFFL)<< S[n][i % 4] | ((result[0]&0xFFFFFFFFL) >>> (32 - S[n][i % 4])));
//循环轮换
long temp = result[3];
result[3] = result[2];
result[2] = result[1];
result[1] = result[0];
result[0] = temp;
}
}
//加入之前计算的结果
result[0] += a;
result[1] += b;
result[2] += c;
result[3] += d;
//防止溢出
for(int n = 0; n < 4 ; n++) {
result[n] &=0xFFFFFFFFL;
}
}
public static void main(String []args){
MD5 md=new MD5();
String message = "helloMD5";
System.out.println("明文:" + message);
System.out.println("小写的密文:" + md.start(message));
System.out.println("大写的密文: " + md.resultMessage.toUpperCase());
//F0F99260B5A02508C71F6D81C15E9A44
//3ED9E5F6855DBCDBCD95AC6C4FE0C0A5
}
}
jQuery.md5.js
/** * jQuery MD5 hash algorithm function * * <code> * Calculate the md5 hash of a String * String $.md5 ( String str ) * </code> * * Calculates the MD5 hash of str using the » RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash. * MD5 (Message-Digest algorithm 5) is a widely-used cryptographic hash function with a 128-bit hash value. MD5 has been employed in a wide variety of security applications, and is also commonly used to check the integrity of data. The generated hash is also non-reversable. Data cannot be retrieved from the message digest, the digest uniquely identifies the data. * MD5 was developed by Professor Ronald L. Rivest in 1994. Its 128 bit (16 byte) message digest makes it a faster implementation than SHA-1. * This script is used to process a variable length message into a fixed-length output of 128 bits using the MD5 algorithm. It is fully compatible with UTF-8 encoding. It is very useful when u want to transfer encrypted passwords over the internet. If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag). * This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin. * * Example * Code * <code> * $.md5("I'm Persian."); * </code> * Result * <code> * "b8c901d0f02223f9761016cfff9d68df" * </code> * * @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com > * @link http://www.semnanweb.com/jquery-plugin/md5.html * @see http://www.webtoolkit.info/ * @license http://www.gnu.org/licenses/gpl.html [GNU General Public License] * @param {jQuery} {md5:function(string)) * @return string */
(function($){
var rotateLeft = function(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
var addUnsigned = function(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ lX8 ^ lY8);
}
}
var F = function(x, y, z) {
return (x & y) | ((~ x) & z);
}
var G = function(x, y, z) {
return (x & z) | (y & (~ z));
}
var H = function(x, y, z) {
return (x ^ y ^ z);
}
var I = function(x, y, z) {
return (y ^ (x | (~ z)));
}
var FF = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var GG = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var HH = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var II = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var convertToWordArray = function(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWordsTempOne = lMessageLength + 8;
var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
};
var wordToHex = function(lValue) {
var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValueTemp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
}
return WordToHexValue;
};
var uTF8Encode = function(string) {
string = string.replace(/\x0d\x0a/g, "\x0a");
var output = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
output += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
output += String.fromCharCode((c >> 6) | 192);
output += String.fromCharCode((c & 63) | 128);
} else {
output += String.fromCharCode((c >> 12) | 224);
output += String.fromCharCode(((c >> 6) & 63) | 128);
output += String.fromCharCode((c & 63) | 128);
}
}
return output;
};
$.extend({
md5: function(string) {
var x = Array();
var k, AA, BB, CC, DD, a, b, c, d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = uTF8Encode(string);
x = convertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k = 0; k < x.length; k += 16) {
AA = a; BB = b; CC = c; DD = d;
a = FF(a, b, c, d, x[k+0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k+1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k+2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k+3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k+4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k+5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k+6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k+7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k+8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k+9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k+10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k+11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k+12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k+13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k+14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k+15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k+1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k+6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k+11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k+0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k+5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k+10], S22, 0x2441453);
c = GG(c, d, a, b, x[k+15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k+4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k+9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k+14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k+3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k+8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k+13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k+2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k+7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k+12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k+5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k+8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k+11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k+14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k+1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k+4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k+7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k+10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k+13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k+0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k+3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k+6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k+9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k+12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k+15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k+2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k+0], S41, 0xF4292244);
d = II(d, a, b, c, x[k+7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k+14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k+5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k+12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k+3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k+10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k+1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k+8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k+15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k+6], S43, 0xA3014314);
b = II(b, c, d, a, x[k+13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k+4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k+11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k+2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k+9], S44, 0xEB86D391);
a = addUnsigned(a, AA);
b = addUnsigned(b, BB);
c = addUnsigned(c, CC);
d = addUnsigned(d, DD);
}
var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
return tempValue.toLowerCase();
}
});
})(jQuery);
<script src="jquery-3.4.1.js"></script>
<script src="jQuery.md5.js"></script>
<script>
//加密
alert($.md5("1234"))
</script>
public class SHA1 {
private static final boolean hexcase = false;
private static final String b64pad = "=";
private static final int chrsz = 8;
// 得到字符串SHA-1值的方法
public static String hex_sha1(String s) {
s = (s == null) ? "" : s;
return binb2hex(core_sha1(str2binb(s), s.length() * chrsz));
}
public static String b64_hmac_sha1(String key, String data) {
return binb2b64(core_hmac_sha1(key, data));
}
public static String b64_sha1(String s) {
s = (s == null) ? "" : s;
return binb2b64(core_sha1(str2binb(s), s.length() * chrsz));
}
private static String binb2b64(int[] binarray) {
String tab = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/";
String str = "";
binarray = strechbinarray(binarray, binarray.length * 4);
for (int i = 0; i < binarray.length * 4; i += 3) {
int triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xff) << 16)
| (((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xff) << 8)
| ((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xff);
for (int j = 0; j < 4; j++) {
if (i * 8 + j * 6 > binarray.length * 32) {
str += b64pad;
} else {
str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3f);
}
}
}
return cleanb64str(str);
}
private static String binb2hex(int[] binarray) {
String hex_tab = hexcase ? "0123456789abcdef" : "0123456789abcdef";
String str = "";
for (int i = 0; i < binarray.length * 4; i++) {
char a = (char) hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xf);
char b = (char) hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xf);
str += (new Character(a).toString() + new Character(b).toString());
}
return str;
}
private static String binb2str(int[] bin) {
String str = "";
int mask = (1 << chrsz) - 1;
for (int i = 0; i < bin.length * 32; i += chrsz) {
str += (char) ((bin[i >> 5] >>> (24 - i % 32)) & mask);
}
return str;
}
private static int bit_rol(int num, int cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
private static String cleanb64str(String str) {
str = (str == null) ? "" : str;
int len = str.length();
if (len <= 1) {
return str;
}
char trailchar = str.charAt(len - 1);
String trailstr = "";
for (int i = len - 1; i >= 0 && str.charAt(i) == trailchar; i--) {
trailstr += str.charAt(i);
}
return str.substring(0, str.indexOf(trailstr));
}
private static int[] complete216(int[] oldbin) {
if (oldbin.length >= 16) {
return oldbin;
}
int[] newbin = new int[16 - oldbin.length];
for (int i = 0; i < newbin.length; newbin[i] = 0, i++)
;
return concat(oldbin, newbin);
}
private static int[] concat(int[] oldbin, int[] newbin) {
int[] retval = new int[oldbin.length + newbin.length];
for (int i = 0; i < (oldbin.length + newbin.length); i++) {
if (i < oldbin.length) {
retval[i] = oldbin[i];
} else {
retval[i] = newbin[i - oldbin.length];
}
}
return retval;
}
private static int[] core_hmac_sha1(String key, String data) {
key = (key == null) ? "" : key;
data = (data == null) ? "" : data;
int[] bkey = complete216(str2binb(key));
if (bkey.length > 16) {
bkey = core_sha1(bkey, key.length() * chrsz);
}
int[] ipad = new int[16];
int[] opad = new int[16];
for (int i = 0; i < 16; ipad[i] = 0, opad[i] = 0, i++)
;
for (int i = 0; i < 16; i++) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5c5c5c5c;
}
int[] hash = core_sha1(concat(ipad, str2binb(data)), 512 + data.length() * chrsz);
return core_sha1(concat(opad, hash), 512 + 160);
}
private static int[] core_sha1(int[] x, int len) {
int size = (len >> 5);
x = strechbinarray(x, size);
x[len >> 5] |= 0x80 << (24 - len % 32);
size = ((len + 64 >> 9) << 4) + 15;
x = strechbinarray(x, size);
x[((len + 64 >> 9) << 4) + 15] = len;
int[] w = new int[80];
int a = 1732584193;
int b = -271733879;
int c = -1732584194;
int d = 271733878;
int e = -1009589776;
for (int i = 0; i < x.length; i += 16) {
int olda = a;
int oldb = b;
int oldc = c;
int oldd = d;
int olde = e;
for (int j = 0; j < 80; j++) {
if (j < 16) {
w[j] = x[i + j];
} else {
w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
int t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
int[] retval = new int[5];
retval[0] = a;
retval[1] = b;
retval[2] = c;
retval[3] = d;
retval[4] = e;
return retval;
}
private static void dotest() {
String key = "key";
String data = "data";
System.out.println("hex_sha1(" + data + ")=" + hex_sha1(data));
System.out.println("b64_sha1(" + data + ")=" + b64_sha1(data));
System.out.println("str_sha1(" + data + ")=" + str_sha1(data));
System.out.println("hex_hmac_sha1(" + key + "," + data + ")=" + hex_hmac_sha1(key, data));
System.out.println("b64_hmac_sha1(" + key + "," + data + ")=" + b64_hmac_sha1(key, data));
System.out.println("str_hmac_sha1(" + key + "," + data + ")=" + str_hmac_sha1(key, data));
}
public static String hex_hmac_sha1(String key, String data) {
return binb2hex(core_hmac_sha1(key, data));
}
private static int rol(int num, int cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
private static int safe_add(int x, int y) {
int lsw = (int) (x & 0xffff) + (int) (y & 0xffff);
int msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xffff);
}
private static int sha1_ft(int t, int b, int c, int d) {
if (t < 20)
return (b & c) | ((~b) & d);
if (t < 40)
return b ^ c ^ d;
if (t < 60)
return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
private static int sha1_kt(int t) {
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
}
private static boolean sha1_vm_test() {
return hexcase ? hex_sha1("abc").equals("a9993e364706816aba3e25717850c26c9cd0d89d") : hex_sha1("abc").equals(
"a9993e364706816aba3e25717850c26c9cd0d89d");
}
public static String str_hmac_sha1(String key, String data) {
return binb2str(core_hmac_sha1(key, data));
}
public static String str_sha1(String s) {
s = (s == null) ? "" : s;
return binb2str(core_sha1(str2binb(s), s.length() * chrsz));
}
private static int[] str2binb(String str) {
str = (str == null) ? "" : str;
int[] tmp = new int[str.length() * chrsz];
int mask = (1 << chrsz) - 1;
for (int i = 0; i < str.length() * chrsz; i += chrsz) {
tmp[i >> 5] |= ((int) (str.charAt(i / chrsz)) & mask) << (24 - i % 32);
}
int len = 0;
for (int i = 0; i < tmp.length && tmp[i] != 0; i++, len++)
;
int[] bin = new int[len];
for (int i = 0; i < len; i++) {
bin[i] = tmp[i];
}
return bin;
}
private static int[] strechbinarray(int[] oldbin, int size) {
int currlen = oldbin.length;
if (currlen >= size + 1) {
return oldbin;
}
int[] newbin = new int[size + 1];
for (int i = 0; i < size; newbin[i] = 0, i++)
;
for (int i = 0; i < currlen; i++) {
newbin[i] = oldbin[i];
}
return newbin;
}
public static void main(String[] args) {
System.out.println("admin的SHA1的值为:" + hex_sha1("123") + ",length=" + hex_sha1("admin").length());
}
}
比较依据 | MD5 | SHA1 |
---|---|---|
代表 | 信息摘要 | 安全哈希算法 |
信息摘要的长度 | 128位 | 160位 |
识别原始消息将需要 | 2 的128次幂操作 | 2的160次幂操作 |
查找两条生成相同消息摘要的消息 | 需要2的64次幂操作 | 需要2的80次幂操作 |
安全 | 较差的 | 中等 |
速度 | 快速 | 慢 |
对称加密解密
非对称加密解密
非对称 就是 商家 生成 公钥 和私钥
公钥 给用户 让用户进行加密 后将加密后的 密文 发给商家
商家在利用私钥进行解密 (有效防止窃取)
对称加密:双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密。
优点:速度快,对称性加密通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。
缺点:在数据传送前,发送方和接收方必须商定好秘钥,然后 使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘 钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。
在对称加密算法中常用的算法有:DES、AES等。
AES:密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节
DES:密钥的长度64位,8个字节。
非对称加密:一对密钥由公钥和私钥组成(可以使用很多对密钥)。私钥解密公钥加密数据,公钥解密私钥加密数据(私钥公钥可以互相加密解密)。
私钥只能由一方保管,不能外泄。公钥可以交给任何请求方。
在非对称加密算法中常用的算法有:
RSA、Elgamal、背包算法、Rabin、Diffie-Hellman、ECC(椭圆曲线加密算法)。
使用最广泛的是RSA算法,Elgamal是另一种常用的非对称加密算法。
缺点:速度较慢
优点:安全
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class AESUtil {
public static final String AES = "AES";
public static final String charset = "UTF-8"; // 编码格式
public static final int keysizeAES = 128;
private static AESUtil instance;
private AESUtil() {
}
// 单例
public static AESUtil getInstance() {
if (instance == null) {
synchronized (AESUtil.class) {
if (instance == null) {
instance = new AESUtil();
}
}
}
return instance;
}
/** * 使用 AES 进行加密 */
public String encode(String res, String key) {
return keyGeneratorES(res, AES, key, keysizeAES, true);
}
/** * 使用 AES 进行解密 */
public String decode(String res, String key) {
return keyGeneratorES(res, AES, key, keysizeAES, false);
}
// 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错
private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
try {
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
if (keysize == 0) {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(new SecureRandom(keyBytes));
} else if (key == null) {
kg.init(keysize);
} else {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(keysize, new SecureRandom(keyBytes));
}
SecretKey sk = kg.generateKey();
SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
if (isEncode) {
cipher.init(Cipher.ENCRYPT_MODE, sks);
byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
return parseByte2HexStr(cipher.doFinal(resBytes));
} else {
cipher.init(Cipher.DECRYPT_MODE, sks);
return new String(cipher.doFinal(parseHexStr2Byte(res)));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 将二进制转换成16进制
private String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
// 将16进制转换为二进制
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
AESUtil instance = AESUtil.getInstance();
//加密
String jiami = instance.encode("hu867682752", "aaa");
System.out.println(jiami);
//解密
String jiemi= instance.decode(jiami, "aaa");
System.out.println(jiemi);
}
}
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class DESUtil {
public static final String DES = "DES";
public static final String charset = "UTF-8"; // 编码格式;默认null为GBK
public static final int keysizeDES = 0;
private static DESUtil instance;
private DESUtil() {
}
// 单例
public static DESUtil getInstance() {
if (instance == null) {
synchronized (DESUtil.class) {
if (instance == null) {
instance = new DESUtil();
}
}
}
return instance;
}
/** * 使用 DES 进行加密 */
public String encode(String res, String key) {
return keyGeneratorES(res, DES, key, keysizeDES, true);
}
/** * 使用 DES 进行解密 */
public String decode(String res, String key) {
return keyGeneratorES(res, DES, key, keysizeDES, false);
}
// 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错
private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
try {
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
if (keysize == 0) {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(new SecureRandom(keyBytes));
} else if (key == null) {
kg.init(keysize);
} else {
byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
kg.init(keysize, new SecureRandom(keyBytes));
}
SecretKey sk = kg.generateKey();
SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
if (isEncode) {
cipher.init(Cipher.ENCRYPT_MODE, sks);
byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
return parseByte2HexStr(cipher.doFinal(resBytes));
} else {
cipher.init(Cipher.DECRYPT_MODE, sks);
return new String(cipher.doFinal(parseHexStr2Byte(res)));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 将二进制转换成16进制
private String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
// 将16进制转换为二进制
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
DESUtil instance= DESUtil.getInstance();
String jiami= instance.encode("12345abc67","abc");
System.out.println(jiami);
String jiemi=instance.decode(jiami,"abc");
System.out.println(jiemi);
}
}
public class XORUtil {
private static XORUtil instance;
private XORUtil() {
}
// 单例
public static XORUtil getInstance() {
if (instance == null) {
synchronized (XORUtil.class) {
if (instance == null) {
instance = new XORUtil();
}
}
}
return instance;
}
/** * 对一个数字进行异或加解密 */
public int code(int res, String key) {
return res ^ key.hashCode();
}
/** * 异或加密 */
public String encode(String res, String key) {
byte[] bs = res.getBytes();
for (int i = 0; i < bs.length; i++) {
bs[i] = (byte) ((bs[i]) ^ key.hashCode());
}
return parseByte2HexStr(bs);
}
/** * 异或解密 */
public String decode(String res, String key) {
byte[] bs = parseHexStr2Byte(res);
for (int i = 0; i < bs.length; i++) {
bs[i] = (byte) ((bs[i]) ^ key.hashCode());
}
return new String(bs);
}
// 将二进制转换成16进制
private String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
// 将16进制转换为二进制
private byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
public static void main(String[] args) {
XORUtil instance= XORUtil.getInstance();
String jiami= instance.encode("124ff","abc");
System.out.println(jiami);
String jiemi = instance.decode(jiami,"abc");
System.out.println(jiemi);
//针对 纯数字 进行加密 和解密
int num_jiami= instance.code(543,"abv");
System.out.println(num_jiami);
int num_jiemi= instance.code(num_jiami,"abv");
System.out.println(num_jiemi);
}
}
import org.apache.commons.codec.binary.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/** * @author yihur * @description RSA加密 * @date 2019/4/3 */
public class RSAUtils {
//前端使用方法
//<script src="js/jsencrypt.js"></script>
// function encryptRequest( text) {
// var encrypt=new JSEncrypt();
// encrypt.setPrivateKey("公秘钥");
//生成密文
// alert(encrypt.encrypt(text))
// }
/** * 用于封装随机产生的公钥与私钥 * * @author yihur * @date 2019/4/4 * @param * @return */
private static Map<Integer, String> keyMap = new HashMap<>();
/** * 随机生成密钥对 * * @param * @return void * @author yihur * @date 2019/4/4 */
public static void genKeyPair() {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 初始化密钥对生成器,密钥大小为96-1024位
assert keyPairGen != null;
keyPairGen.initialize(1024, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
keyMap.put(0, publicKeyString); //0表示公钥
keyMap.put(1, privateKeyString); //1表示私钥
}
/** * RSA公钥加密 * * @param str 加密字符串 * @param publicKey 公钥 * @return 密文 */
public static String encrypt(String str, String publicKey) {
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = null;
String outStr = null;
try {
pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
} catch (InvalidKeySpecException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
//RSA加密
return outStr;
}
/** * RSA私钥解密 * * @param str 加密字符串 * @param privateKey 私钥 * @return 铭文 */
public static String decrypt(String str, String privateKey) {
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = null;
//RSA解密
Cipher cipher = null;
String outStr = null;
try {
priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
outStr = new String(cipher.doFinal(inputByte));
} catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
}
return outStr;
}
public static void main(String[] args) {
//生成公钥和私钥
genKeyPair();
String publicKey=keyMap.get(0);
String privateKey=keyMap.get(1);
//加密字符串
String message = "df723820";
System.out.println("随机生成的公钥为:" + publicKey);
System.out.println("随机生成的私钥为:" + privateKey);
//加密 生成密文
String messageEn = encrypt(message, publicKey);
System.out.println("加密后的字符串为:" + messageEn);
//解密
String messageDe = decrypt(messageEn, privateKey);
System.out.println("还原后的字符串为:" + messageDe);
}
}
jsencrypt.js
链接:https://pan.baidu.com/s/1p4bTF8w_nw5pBieIr_EFyA
提取码:1234
使用步骤
后端 生成公钥和私秘钥
前端 利用公秘钥 生成密文 传递给后端
后端在 利用私秘钥 解析密文
当然前端也是可以生成公钥和私秘钥 但是不安全 一般都是交给后端
公秘钥和私密钥生成
前端
生成公秘钥和私密钥 和使用
var encrypt=new JSEncrypt();
var publicKey = encrypt.getPublicKey();
var privateKey = encrypt.getPrivateKey();
alert("公钥\n"+publicKey)
alert("私钥\n"+privateKey)
//前端使用方法
<script src="js/jsencrypt.js"></script>
<script>
function encryptRequest( text) {
var encrypt=new JSEncrypt();
encrypt.setPrivateKey("公秘钥");
//生成密文
alert(encrypt.encrypt(text))
}
</script>
后端
生成公秘钥和私密钥 和使用
//生成公钥和私钥
public static void main(String[] args) {
//生成公钥和私钥
genKeyPair();
String publicKey=keyMap.get(0);
String privateKey=keyMap.get(1);
//加密字符串
String message = "df723820";
System.out.println("随机生成的公钥为:" + publicKey);
System.out.println("随机生成的私钥为:" + privateKey);
//利用公秘钥加密 生成密文 (这一步可以放到前端 )
String messageEn = encrypt(message, publicKey);
System.out.println("加密后的字符串为:" + messageEn);
//解密 (传来的密文 利用私钥 解析出来 )
String messageDe = decrypt(messageEn, privateKey);
System.out.println("还原后的字符串为:" + messageDe);
}
需要导入AESUtil工具类
然后添加以下内容
package com.bda.www.aa;
import java.beans.beancontext.BeanContext;
import java.io.*;
import java.util.*;
public class file_jia_mi__jie_mi_Wen_ben {
/* * 注意事项 加密后 会将原文件 删除 可以修改 * 解密后也会将 原文件删除 可以修改 * */
//缓存大小
private static final int HUAN_CHUN=10000;
private static AESUtil instance = AESUtil.getInstance();
public static boolean jiami(String fileName, String key) {
long startTime = System.currentTimeMillis();
int b = fileName.lastIndexOf(".");
String b2 = fileName.substring(0,b); //获取.前面内容
int bf = fileName.lastIndexOf(".");
String bf1 = fileName.substring(bf); //获取后缀
String file_luj=b2+"_encrypt_"+bf1;
try(
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
new File(fileName))));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(new File(file_luj))));
) {
StringBuilder stringBuilder=new StringBuilder();
String line=br.readLine();
int i=0;
boolean pd=false;
int num=0;
while(true) {
stringBuilder.append(line+"\n");
if(i==HUAN_CHUN){
bw.write(instance.encode(stringBuilder.toString(),key)+"\n"); //写入
i=0;
stringBuilder=new StringBuilder();
pd=true;
num++;
}
i++;
line=br.readLine();//循环每次读取一行数据
if (line==null){
if (!pd){
bw.write(instance.encode(stringBuilder.toString(),key)+"\n"); //写入
num++;
}
break;
}
pd=false;
}
System.out.println("一共写入了几次"+num);
} catch (IOException e) {
e.printStackTrace();
return false;
}
//删除加密前文件
File file1 = new File(fileName);
file1.delete();
//想命名的原文件的路径
File file = new File(file_luj);
String rootPath = file.getParent();
String a=rootPath + File.separator + "_encrypt_"+Name_tuP()+bf1;
System.out.println(a);
//将原文件更改为f:\a\b.xlsx,其中路径是必要的。注意
file.renameTo(new File( a));
file.delete(); //删除原文件
long endTime = System.currentTimeMillis();
System.out.println("加密花费时间为:" + (endTime - startTime));
return true;
}
public static boolean jiemi(String fileName, String key) {
//将二进制转换为 字符
// 然后 解密
// 在 二进制写入
long startTime = System.currentTimeMillis();
int b = fileName.lastIndexOf(".");
String b2 = fileName.substring(0,b); //获取.前面内容
int bf = fileName.lastIndexOf(".");
String bf1 = fileName.substring(bf); //获取后缀
String file_luj=b2+"_decode_"+bf1;
try(
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
new File(fileName))));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(new File(file_luj))));
) {
StringBuilder stringBuilder=new StringBuilder();
String line=br.readLine();
int i=0;
boolean pd=false;
int num=0;
while(true) {
stringBuilder.append(instance.decode(line,key));
if(i==HUAN_CHUN/10){
bw.write(stringBuilder.toString()); //写入
i=0;
stringBuilder=new StringBuilder();
pd=true;
num++;
}
i++;
line=br.readLine();//循环每次读取一行数据
if (line==null){
if (!pd){
bw.write(stringBuilder.toString()); //写入
num++;
}
break;
}
pd=false;
}
System.out.println("一共写入了几次"+num);
} catch (IOException e) {
e.printStackTrace();
return false;
}
//删除加密文件
File file1 = new File(fileName);
file1.delete();
//想命名的原文件的路径
File file = new File(file_luj);
String rootPath = file.getParent();
String a=rootPath + File.separator + "_decode_"+Name_tuP()+bf1;
System.out.println(a);
//将原文件更改为f:\a\b.xlsx,其中路径是必要的。注意
file.renameTo(new File( a));
file.delete(); //删除原文件
long endTime = System.currentTimeMillis();
System.out.println("解密花费时间为:" + (endTime - startTime));
return true;
}
public static String Name_tuP(){
char[] ch={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char[] Ch={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
Calendar cal = Calendar.getInstance();
Random sun=new Random();
int num1=sun.nextInt(1000);//0-1000随机数
StringBuilder time=new StringBuilder();
time.append(num1+"-");//随机数
time.append(cal.get(Calendar.YEAR)); //年
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.MONTH) + 1);//月
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.DAY_OF_MONTH));//日
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.HOUR_OF_DAY));//时
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.MINUTE));//分
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.SECOND));//秒
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]+"-");
int num=sun.nextInt(1000);//0-1000随机数
time.append(num);//随机数
return time.toString();
}
}
使用
import org.junit.Test;
public class test {
//必须是txt文件
@Test
public void tes(){
//filename 路径 key 秘钥
boolean pd= file_jia_mi__jie_mi_Wen_ben.jiami("加密的文件","aaa");
if(pd){
System.out.println("加密成功");
}else{
System.out.println("加密失败");
}
}
//解密
@Test
public void ss(){
//filename 文件路径 key秘钥(要和加密的秘钥对应)
boolean pd1= file_jia_mi__jie_mi_Wen_ben.jiemi("解密的文件","aaa");
if(pd1){
System.out.println("解密成功");
}else{
System.out.println("解密失败");
}
}
}
需要导入AESUtil工具类
然后添加以下内容
import java.io.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
public class file_jia_mi__jie_mi_erjinzhi {
private static AESUtil instance = AESUtil.getInstance();
public static boolean jiami(String fileName, String key) {
int b = fileName.lastIndexOf(".");
String b2 = fileName.substring(0,b); //获取.前面内容
String file_luj=b2+"_"+Name_tuP()+".txt";
List<String> str = new ArrayList<>();
try (
FileInputStream fileInputStream = new FileInputStream(fileName);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
FileWriter fileWriter = new FileWriter(file_luj);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
) {
int data;
while ((data = dataInputStream.read()) != -1) {
bufferedWriter.write(instance.encode(String.valueOf(data),key)+"\n");
}
return true;
} catch (IOException e) {
return false;
}finally {
File file = new File(fileName);
file.delete();
}
}
public static boolean jiemi(String fileName,String key,String suffix){
int bf = fileName.lastIndexOf(".");
String bf1 = fileName.substring(bf+1); //获取后缀
if (!bf1.equals("txt")){
System.out.println("不能解密此类型文件,只能解密 加密后的txt文本文件");
return false;
}
int b = fileName.lastIndexOf(".");
String b2 = fileName.substring(0,b); //获取.前面内容路径
String file_luj=b2+"_"+Name_tuP()+"."+suffix;
//解密 将文件内的加密信息读取出来 然后解密完 在覆盖回去
try(
FileReader fr=new FileReader(fileName);
BufferedReader br=new BufferedReader(fr);
FileOutputStream fileOutputStream=new FileOutputStream(file_luj);
DataOutputStream dataOutputStream=new DataOutputStream(fileOutputStream);
) {
String line=br.readLine();
while(line!=null) {
dataOutputStream.write(Integer.parseInt( instance.decode(line.toString(), key)));
line=br.readLine();//循环每次读取一行数据
}
//删除原文件
return true;
} catch (IOException e) {
return false;
}finally {
File file = new File(fileName);
file.delete();
}
}
public static String Name_tuP(){
char[] ch={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char[] Ch={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
Calendar cal = Calendar.getInstance();
Random sun=new Random();
int num1=sun.nextInt(1000);//0-1000随机数
StringBuilder time=new StringBuilder();
time.append(num1+"-");//随机数
time.append(cal.get(Calendar.YEAR)); //年
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.MONTH) + 1);//月
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.DAY_OF_MONTH));//日
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.HOUR_OF_DAY));//时
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.MINUTE));//分
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]);
time.append(cal.get(Calendar.SECOND));//秒
time.append(ch[sun.nextInt(ch.length)]);
time.append(Ch[sun.nextInt(ch.length)]+"-");
int num=sun.nextInt(1000);//0-1000随机数
time.append(num);//随机数
return time.toString();
}
}
import org.junit.Test;
public class test {
//12.3mb的视频加密后 的文件大小 400mb左右 大约在32倍左右
//148kb 图片加密后 的文件大小 4.79 mb左右 大约在32倍左右
//可以看出来 加密文件的大小会是 原文件的 32倍大小
public static void main(String[] args) {
//filename 路径 key 秘钥
boolean pd= file_jia_mi__jie_mi_erjinzhi.jiami("加密文件","aaa");
if(pd){
System.out.println("加密成功");
}else{
System.out.println("加密失败");
}
}
@Test
public void jiemi(){
// filename 文件路径 key秘钥(要和加密的秘钥对应) suffix 生成的文件的后缀名(也就是文件类型)
// //这里注意的是别瞎搞 加密前的文件是什么类型 解密后也进量是什么类型 比如png(加密前)=png(解密后) 否则有可能出现生成失败的情况
boolean pd= file_jia_mi__jie_mi_erjinzhi.jiemi("解密文件","aaa","png");
if(pd){
System.out.println("解密成功");
}else{
System.out.println("解密失败");
}
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_45203607/article/details/120238328
内容来源于网络,如有侵权,请联系作者删除!